//=============================================================================
/**
 *
 *	@file		encount_effect_yasei.c
 *	@brief		エンカウントエフェクト パタパタ系（GS野生)
 *	@author		hosaka genya
 *	@data		2009.03.05
 *
 */
//=============================================================================
#include "common.h"
#include "system/lib_pack.h"
#include "system/brightness.h"
#include "system/snd_tool.h"
#include "fieldsys.h"
#include "fieldmap_work.h"
#include "field_event.h"
#include "fld_motion_bl.h"
#include "encount_effect_def.h"
#include "system/wipe.h"
#include "system/fontproc.h"
#include "field_encounteffect.naix"
#include "savedata/mystatus.h"
#include "include/battle/trtype_def.h"
#include "include/battle/trno_def.h"
#include "include/msgdata/msg.naix"

#include "field/fieldmap.h"

#include "encount_effect_yasei.h"

//-------------------------------------
///		パタパタ閉じていくようなエンカウント
//=====================================
//#define ENCOUNT_PATAPATA_BGMSYNC	//	PATAPATAをBGMSYNCさせるか


//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
//	名木橋テスト用		以下、全て消してかまいません！
//	09.03.05
//		関数自体は消しましたが、memoは有用そうなので残してあります by hosaka genya
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
//
//
//	memo書き
//	・エンカウントエフェクトで使用できるBG面について
//		0	3D
//		1	エフェクト用１
//		2	エフェクト用２	（天気で使用）
//		3	フォント用
//		基本、BG1を使うが、2面必要な場合は、BG3を使う。
//		天気が出ない箇所ならば、合計3面使用できる。
//
//	・FOG
//		お天気で使用。
//
//	・ラスタースクロール
//		ラスタースクロールとは、画面の走査タイミングに合わせて画面をスクロールする方法。もしくはそれによって得られる画面効果。
//		走査線ごとにスクロールできるので、走査線ごとに異なるスクロールをさせると、例えばドラクエのたびの扉のようなことがができる。
//		DSでは2D面に対して、H方向（水平）、V方向（垂直）へラスタスクロールできる。（というかBGのスクロールはラスタースクロール）
//		たたし、V方向のカウンタ値（今何ライン目か）は取得できるのだが、H方向のカウンタ値は取得できない。
//		よって画面が横揺れするのは出来ても、縦ゆれすることができない（と思われる）
//		なお、仕様上、3D面はV方向（垂直）のラスタスクロールができない。
//
//
//	・ハードウェアウィンドウ
//		2枚使用可能。
//		なお、ハードウェアウィンドウとラスター（VBlank割り込み）を使ってるのがワイプシステム。
//		よってワイプ中には不可能。
//
//
//	・キャプチャー
//		画面上の絵を、VRAMにピクセルごとの絵（ウィンドウズのBMPのようなもの）として吐き出し、
//		VRAMの絵を直接LCDに転送するモードで表示する。なお、厳密には色情報が劣化している。
//		キャプチャーをすると3Dの絵を2D化できることから、ラスタスクロールができるのではないかと思われる。
//		また、ちょくせつVRAMにあるピクセルの絵をいじることで、色情報をいじり、グレースケールやセピアに変換することも可能。
//		ただし、VRAM128を割り当てるため、当然VRAMが余っていない場合、どこからかのVRAMをとってくることになり、そこの画像が表示できなくなる。（現在は下画面が使えなくなる）
//		ので（下画面など）そこだけ早めに暗くするなど対処が必要。
//		キャプチャーと実際の絵をブレンドしつつずらして表示するとモーションブラーになる。
//
//
//	・シーケンスローカル変数について
//		シーケンスごとに16個の変数を持っていて、
//		サウンドとプログラム相互に使用できる。
//		例えば、サウンド側で任意のタイミングに書き込んだ値を
//		プログラムで読み取り、そのタイミングに表示を行ったり、
//		プログラム側で変数に書き込み、サウンドが書き込んだ値を見て、
//		曲調を変えたり、とったことができる。
//		（シーケンスデータマニュアル31ページ）
//
//		エンカウントでは曲との同期で使用する（予定）
//
//		▼09.06.11 追記 by hosaka genya
//		・DSは閉開を急速に行なうと曲がズレ、
//		　曲データに埋め込んだ変数を取りこぼすことあるので、
//		　エンカウント時の曲同期は取りやめました。
//
//
//-----------------------------------------------------------------------------


//=============================================================================
/**
 *								構造体定義
 */
//=============================================================================
//-----------------------------------------------------------------------------
/**
 *		ここから以下、名木橋追加分（080519~）
 */
//-----------------------------------------------------------------------------

//	キャラクタでBMPをブラシに塗っていくシステム
#define ENCOUNT_BRUSH_ANGLE_VELOCITY	(0x04)				//	折り返し後角加速度
#define ENCOUNT_BRUSH_SPEED_VELOCITY	(FX32_CONST(0.1))		//	折り返し後スピード加速度
#define ENCOUNT_BRUSH_SPEED_MAXIMUM		(FX32_CONST(30))	//	スピード上限

#define ENCOUNT_BRUSH_FADE_DIV	(FX32_CONST(0.8))			//	定義を外すと行わない

struct _ENC_BMP_CHR_BRUSH {
	GF_BGL_BMPWIN			*p_bmp;
	NNSG2dCharacterData		*p_chardata;
	void	*p_char;
	ENC_MOVE_WORK move_x;
	ENC_MOVE_WORK move_y;
	s16	src_x;
	s16	src_y;
	u16	chr_w;
	u8	piece_sync;			//	ひとつの直線を書くシンク
	u8	reflex_point_now;
	u8	dir_flg;
	u8	col;
	u8	init_flg;
	u8	dummy;
};
#define ENC_BMP_CHR_BRUSH_STAMP_CNT			(3)		//	1シンク中何回張るか（3以上だと処理負荷）
#define ENC_BMP_CHR_BRUSH_RANGE_MARGIN		(16)
#define ENC_BMP_CHR_BRUSH_RANGE_WIDTH_S		(-ENC_BMP_CHR_BRUSH_RANGE_MARGIN)
#define ENC_BMP_CHR_BRUSH_RANGE_WIDTH_E		(256+ENC_BMP_CHR_BRUSH_RANGE_MARGIN)
#define ENC_BMP_CHR_BRUSH_RANGE_HEIGHT_S	(-ENC_BMP_CHR_BRUSH_RANGE_MARGIN)
#define ENC_BMP_CHR_BRUSH_RANGE_HEIGHT_E	(192+ENC_BMP_CHR_BRUSH_RANGE_MARGIN)
#define ENC_BMP_CHR_BRUSH_RANGE_WIDTH		(ENC_BMP_CHR_BRUSH_RANGE_WIDTH_E-ENC_BMP_CHR_BRUSH_RANGE_WIDTH_S)
#define ENC_BMP_CHR_BRUSH_RANGE_HEIGHT		(ENC_BMP_CHR_BRUSH_RANGE_HEIGHT_E-ENC_BMP_CHR_BRUSH_RANGE_HEIGHT_S)
static void ENC_BMP_BRUSH_GetDispEdge( u8 dir, s16 now, u16 chr_w, s16 *p_x, s16 *p_y );
static BOOL ENC_BMP_BRUSH_GetReflexPoint( u8 *p_flg, s16 now, u16 chr_w, s16 *p_sx, s16 *p_sy, s16 *p_ex, s16 *p_ey );

//	キャラクタでBMPに手書きで塗っていくシステム
struct _ENC_BMP_HAND_BRUSH {
	GF_BGL_BMPWIN			*p_bmp;
	NNSG2dCharacterData		*p_chardata;
	ENC_HAND_DRAW			*p_hand;
	void *p_char;
	s16 src_x;
	s16 src_y;
	u8 col;
	u8 init_flg;
};

//	手書き再現オブジェクト
typedef struct _ENC_HAND_DRAW {
	const ENC_HAND_DRAW_POS_TBL *cp_tbl;
	fx32	fxcnt_add;
	fx32	fxcnt;
	u16		cnt_max;
	u16		move_flg;
};
static void GetPosTblLiner( const ENC_HAND_DRAW_POS_TBL cp_tbl[], fx32 fxcnt,s16 *p_out_x, s16 *p_out_y );
static void LinerRatio( s16 s_x, s16 s_y, s16 e_x, s16 e_y, fx32 pos, s16 *p_out_x, s16 *p_out_y );

//-------------------------------------
//
//	ビットマップ操作
//
//=====================================
// ビットマップブロックランダム埋め尽くしシステム
#define ENCOUNT_BLOCK_RND_WIDTH		( 32 )	// ブロックサイズ
#define ENCOUNT_BLOCK_RND_HEIGHT	( 32 )	// ブロックサイズ
#define ENCOUNT_BLOCK_RND_X_NUM		( 8 )	// 横の数
#define ENCOUNT_BLOCK_RND_Y_NUM		( 6 )	// 縦の数
#define ENCOUNT_BLOCK_RND_OBJNUM	( ENCOUNT_BLOCK_RND_X_NUM * ENCOUNT_BLOCK_RND_Y_NUM )	// xブロックで埋める

#define NONREPEATRND_BUFF_MAX		( 128 )	//	バッファサイズ
//	重複しないランダム
typedef struct
{
	u16	tbl[NONREPEATRND_BUFF_MAX];	//	重複禁止用テーブル
	u32	idx;						//	インデックス
	u32	max;						//	ランダム最大値
}ENC_NONREPEATRND_WORK;
static void ENC_InitNonRepeatRnd( ENC_NONREPEATRND_WORK *p_work, u32 max );
static u16 ENC_GetNonRepeatRnd( ENC_NONREPEATRND_WORK *p_work );

//	キャラクタでBMPにスタンプしていく
struct _ENC_BMP_CHR_FILL {
	GF_BGL_BMPWIN			*p_bmp;
	ENC_NONREPEATRND_WORK	rnd;
	NNSG2dCharacterData		*p_chardata;
	void *p_char;
	u8 stamp_count;
	u8 start_sync;
	s8 wait;
	u8 col;
	u8 init_flg;
	u8 dummy[3];

};

// ビットマップウィンドウ塗りつぶし拡大オブジェクト
// 例）　・→■	へぬりつぶされる	｜→■　や　―→■も可
typedef struct _ENC_BMP_FILL_SPREAD {
	ENC_MOVE_WORK move_w;
	ENC_MOVE_WORK move_h;
	GF_BGL_BMPWIN* p_bmp;
	s16 x;
	s16 y;
	u8 move_flg;
	u8 col;
};

//	パタパタとぬりつぶされていくシステム
// ビットマップブロックランダム埋め尽くしシステム
#define ENCOUNT_PATAPATA_FILL_WIDTH		( 32 )	// ブロックサイズ
#define ENCOUNT_PATAPATA_FILL_HEIGHT	( 32 )	// ブロックサイズ
#define ENCOUNT_PATAPATA_FILL_X_NUM		( 8 )	// 横の数
#define ENCOUNT_PATAPATA_FILL_Y_NUM		( 6 )	// 縦の数
#define ENCOUNT_PATAPATA_FILL_OBJNUM	( ENCOUNT_PATAPATA_FILL_X_NUM * ENCOUNT_PATAPATA_FILL_Y_NUM )	// xブロックで埋める

// 塗りつぶしテーブル　曲同期しない版
static const u8 ENCOUNT_PATAPATA_FILL_MoveParam[ ENCOUNT_PATAPATA_FILL_OBJNUM/2] = {	// 出てくる順番テーブル
	 0,  1,  2,  3,  4,  5,  6,  7,
	15, 14, 13, 12, 11, 10,  9,  8,
	16, 17, 18, 19, 20, 21, 22, 23,
};
//	正順と逆順（片方だけマクロだと[]と()で使い方が違うくなるので統一）
#define ENCOUNT_PATAPATA_FILL_MoveParam_Order(x)	(ENCOUNT_PATAPATA_FILL_MoveParam[ x ])
#define ENCOUNT_PATAPATA_FILL_MoveParam_Reverse(x) (ENCOUNT_PATAPATA_FILL_OBJNUM - 1 - ENCOUNT_PATAPATA_FILL_MoveParam[ x ])

// 左右逆VER
static const u8 ENCOUNT_PATAPATA_FILL_MoveParam2[ ENCOUNT_PATAPATA_FILL_OBJNUM/2] = {	// 出てくる順番テーブル
	 7,  6,  5,  4,  3,  2,  1,  0,
	 8,  9, 10, 11, 12, 13, 14, 15,
	23, 22, 21, 20, 19, 18, 17, 16,
};
//	正順と逆順（片方だけマクロだと[]と()で使い方が違うくなるので統一）
#define ENCOUNT_PATAPATA_FILL_MoveParam_Order_N(x)	(ENCOUNT_PATAPATA_FILL_MoveParam2[ x ])
#define ENCOUNT_PATAPATA_FILL_MoveParam_Reverse_N(x) (ENCOUNT_PATAPATA_FILL_OBJNUM - 1 - ENCOUNT_PATAPATA_FILL_MoveParam2[ x ])

struct _ENC_BMP_PATAPATA_FILL {
	GF_BGL_BMPWIN		*p_bmp;
	ENC_BMP_FILL_SPREAD	*p_fill[ENCOUNT_PATAPATA_FILL_OBJNUM];
	u8	block_count;
	u8	block_end_count;
	u8	one_start_sync;
	u8	one_fill_sync;
	s8	wait;
	u8	col;
	u8	init_flg;
	u8	b_morning : 1;
	u8	dummy : 7;
};

//	BMPに対する操作
static void ENC_BMP_Point( GF_BGL_BMPWIN* p_bmp, s32 x, s32 y, u8 col );
static void ENC_BMP_StampCharacter( GF_BGL_BMPWIN* p_bmp, const NNSG2dCharacterData *cp_chardata, s16 x, s16 y, u8 col );
static void ENC_BMP_StampCharacterCont( GF_BGL_BMPWIN* p_bmp, const NNSG2dCharacterData *cp_chardata, s16 s_x, s16 s_y, s16 e_x, s16 e_y, u8 num, u8 col );

//	キャラクタに対する操作
static u8 ENC_CHR_GetDot16( const NNSG2dCharacterData *cp_chardata, u16 x, u16 y );
static void ENC_CHR_SetDot16( NNSG2dCharacterData *p_chardata, u8 dot, u16 x, u16 y );

//--------------------------------------------------------------
///	ビットマップランダム塗りつぶし
//==============================================================
struct _ENC_BMP_RND_FILL{
	GF_BGL_BMPWIN		*p_bmp;
	ENC_NONREPEATRND_WORK	rnd;
	u8	block_count;
	u8	start_sync;
	s8	wait;
	u8	col;
	u8	init_flg;
	u8	dummy[3];
};

//	ビットマップにキャラクタをランダムでスタンプしていくシステム
#define ENCOUNT_STAMP_RND_WIDTH		( 32 )	// キャラのサイズ
#define ENCOUNT_STAMP_RND_HEIGHT	( 32 )	// キャラサイズ
#define ENCOUNT_STAMP_RND_X_NUM		( 8 )	// 横の数
#define ENCOUNT_STAMP_RND_Y_NUM		( 6 )	// 縦の数
#define	ENCOUNT_STAMP_CHR_PRESSNUM	( ENCOUNT_STAMP_RND_X_NUM * ENCOUNT_STAMP_RND_Y_NUM )	//	押す回数

//-------------------------------------
//	曲同期類
//=====================================
//	曲のタイミングに合わせて塗りつぶす
struct _ENC_BMP_SYNCBGM_RNDFILL {
	GF_BGL_BMPWIN			*p_bmp;
	ENC_NONREPEATRND_WORK		rnd;
	ENC_SYNCBGM_TIMING_WORK	timing;
	u8	block_count;
	u8	start_num;		//	何個発射するか
	u8	col;
	u8	init_flg;
	u8	dummy[3];
};

//	曲のタイミングに合わせてパタパタ移動
struct _ENC_BMP_SYNCBGM_PATAFILL {
	GF_BGL_BMPWIN			*p_bmp;
	ENC_SYNCBGM_TIMING_WORK	timing;
	ENC_BMP_FILL_SPREAD	*p_fill[ENCOUNT_PATAPATA_FILL_OBJNUM];
	u8	block_count;
	u8	block_end_count;
	u8	one_fill_sync;
	u8	move_obj_num;
	u8	col;
	u8	init_flg;
};
// xブロックで埋める 曲同期版
static const u8 ENCOUNT_SYNCBGM_PATAFILL_MoveParam[ ENCOUNT_PATAPATA_FILL_OBJNUM] = {	// 出てくる順番テーブル
	 0, 47,  1, 46,  2, 45,  3, 44,  4, 43,  5, 42,  6, 41,  7, 40,
	15, 32, 14, 33, 13, 34, 12, 35, 11, 36, 10, 37,  9, 38,  8, 39,
	16, 31, 17, 30, 18, 29, 19, 28, 20, 27, 21, 26, 22, 25, 23, 24,
};

//-------------------------------------
//	キャプチャ類
//=====================================
//#define CAPTURE_SRC_VRAM_KEEP		//	キャプチャ前のVRAM状態を保存するか否か（メモリ128kかかります）

//	キャプチャシステムワーク
typedef struct _ENC_CAPTURE {
	GXVRamLCDC			src_lcdc;
	ENC_CAPTURE_PARAM	param;

#ifdef CAPTURE_SRC_VRAM_KEEP
	void				*p_vram_data;
#endif  // CAPTURE_SRC_VRAM_KEEP
};

//	キャプチャ用VRAM情報テーブル
static const struct {
	void		*LCDC_ADDR;
	int			BG_ADDR;
	u32			SIZE;
	GXDispMode	DISPMODE;
}VRAM_TBL[]	= {
	{
		(void*)HW_LCDC_VRAM_A,
		GX_VRAM_BG_128_A,
		HW_VRAM_A_SIZE,
		GX_DISPMODE_VRAM_A,
	},
	{
		(void*)HW_LCDC_VRAM_B,
		GX_VRAM_BG_128_B,
		HW_VRAM_B_SIZE,
		GX_DISPMODE_VRAM_B,
	},
	{
		(void*)HW_LCDC_VRAM_C,
		GX_VRAM_BG_128_C,
		HW_VRAM_C_SIZE,
		GX_DISPMODE_VRAM_C,
	},
	{
		(void*)HW_LCDC_VRAM_D,
		GX_VRAM_BG_128_D,
		HW_VRAM_D_SIZE,
		GX_DISPMODE_VRAM_D,
	},
};

//----------------------------------------------------------------------------
/**
 *		【ビットマップウィンドウ拡大塗りつぶし】
 *	@brief	ワークの確保
 *
 *	@param	heapID	ヒープID
 *
 *	@return	ワーク
 */
//-----------------------------------------------------------------------------
ENC_BMP_FILL_SPREAD* ENC_BMP_FillSpreadAlloc( u32 heapID )
{
	ENC_BMP_FILL_SPREAD* p_work;

	p_work = sys_AllocMemory( heapID, sizeof(ENC_BMP_FILL_SPREAD) );
	memset( p_work, 0, sizeof(ENC_BMP_FILL_SPREAD) );
	return p_work;
}

//----------------------------------------------------------------------------
/**
 *		【ビットマップウィンドウ拡大塗りつぶし】
 *	@brief	ワーク破棄
 *
 *	@param	p_work	ワーク
 */
//-----------------------------------------------------------------------------
void ENC_BMP_FillSpreadDelete( ENC_BMP_FILL_SPREAD* p_work )
{
	sys_FreeMemoryEz( p_work );
}

//----------------------------------------------------------------------------
/**
 *		【ビットマップウィンドウ拡大塗りつぶし】
 *	@brief	動さ開始

 *	@param	ENC_BMP_FILL_SPREAD* p_work	ワーク
 *	@param	x			中心座標
 *	@param	x			中心座標
 *	@param	sync		塗りつぶしシンク
 *	@param	p_bmp		書き込むビットマップウィンドウ
 *	@param	s_w			塗りつぶし開始幅(0だと中心座標）
 *	@param	s_h			塗りつぶし開始高さ
 *	@param	e_w			塗りつぶし終了幅
 *	@param	e_h			塗りつぶし終了高さ
 *	@param	col			塗りつぶす色
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_BMP_FillSpreadStart( ENC_BMP_FILL_SPREAD* p_work, int x, int y, int sync, GF_BGL_BMPWIN* p_bmp, int s_w, int s_h, int e_w, int e_h, u8 col  )
{
	GF_ASSERT( p_work->move_flg == FALSE );

	// 動さパラメータ
	ENC_MoveReq( &p_work->move_w, s_w, e_w, sync );
	ENC_MoveReq( &p_work->move_h, s_h, e_h, sync );

	// その他パラメータ
	p_work->p_bmp	= p_bmp;	// 塗りつぶすビットマップ
	p_work->x		= x;		// 塗りつぶし中心座標
	p_work->y		= y;		// 塗りつぶし中心座標
	p_work->col		= col;		// 塗りつぶしカラー番号

	p_work->move_flg = TRUE;
}

//----------------------------------------------------------------------------
/**
 *		【ビットマップウィンドウ拡大塗りつぶし】
 *	@brief	動さメイン
 *
 *	@param	p_work	ワーク
 *
 *	@retval	TRUE	終了
 *	@retval	FALSE	途中
 */
//-----------------------------------------------------------------------------
BOOL ENC_BMP_FillSpreadMain( ENC_BMP_FILL_SPREAD* p_work )
{
	BOOL result;
	s16 top, bottom, left, right;
	if( p_work->move_flg == FALSE ){
		return TRUE;
	}

	result = ENC_MoveMain( &p_work->move_w );
	result |= ENC_MoveMain( &p_work->move_h );

	left = p_work->x - (p_work->move_w.x/2);
	top = p_work->y - (p_work->move_h.x/2);
	right = p_work->x + (p_work->move_w.x/2);
	bottom = p_work->y + (p_work->move_h.x/2);

	// ビットマップ塗りつぶし
	ENC_BMP_Fill( p_work->p_bmp, top, bottom, left, right, p_work->col );

	return result;
}

//----------------------------------------------------------------------------
/**
 * 【手書き再現オブジェクト】
 *	@brief	手書き再現オブジェクト作成
 *
 *	@param	u32 heapID					ヒープ
 *	@param	ENC_HAND_DRAW_POS_TBL tbl[]	手書き情報
 *
 *	@return	ワーク
 */
//-----------------------------------------------------------------------------
ENC_HAND_DRAW* ENC_HandDrawAlloc( u32 heapID )
{
	ENC_HAND_DRAW* p_work;

	p_work = sys_AllocMemory( heapID, sizeof(ENC_HAND_DRAW) );
	memset( p_work, 0, sizeof(ENC_HAND_DRAW) );
	return p_work;
}

//----------------------------------------------------------------------------
/**
 * 【手書き再現オブジェクト】
 *	@brief	手書き再現オブジェクト破棄
 *
 *	@param	ENC_HAND_DRAW *p_work ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_HandDrawDelete( ENC_HAND_DRAW *p_work )
{
	sys_FreeMemoryEz( p_work );
}

//----------------------------------------------------------------------------
/**
 * 【手書き再現オブジェクト】
 *	@brief	手書き再現開始
 *
 *	@param	ENC_HAND_DRAW *p_work ワーク
 *	@param	cp_tbl			手書き情報
 *	@param	sync			手書きを再現させるシンク（等速の場合NELEMSを入れればよい）
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_HandDrawStart( ENC_HAND_DRAW *p_work, const ENC_HAND_DRAW_POS_TBL cp_tbl[], u16 sync )
{
	p_work->cp_tbl	= cp_tbl;

	p_work->cnt_max		= 0;
	p_work->move_flg	= 1;

	//	配列数数え
	while( !(p_work->cp_tbl[ p_work->cnt_max ].x == ENC_HAND_DRAW_POS_TBL_END
		  && p_work->cp_tbl[ p_work->cnt_max ].y == ENC_HAND_DRAW_POS_TBL_END) ) {
		p_work->cnt_max++;
	}

	p_work->fxcnt_add	= FX32_CONST(p_work->cnt_max) / sync;
	p_work->fxcnt		= 0;
}

//----------------------------------------------------------------------------
/**
 * 【手書き再現オブジェクト】
 *	@brief	手書き再現開始
 *
 *	@param	ENC_HAND_DRAW *p_work	ワーク
 *	@param	*p_x					[out]取得座標X	NULLなら取得しない
 *	@param	*p_y					[out]取得座標Y	NULLなら取得しない
 *
 *	@retval	TRUE					再現終了
 *	@retval FALSE					再現中
 */
//-----------------------------------------------------------------------------
BOOL ENC_HandDrawGetPosMain( ENC_HAND_DRAW *p_work, s16 *p_x, s16 *p_y )
{
	if( p_work->move_flg == 0 ){
		return TRUE;
	}

	//	終了チェック
	if( (p_work->fxcnt >> FX32_SHIFT) >= p_work->cnt_max - 1 ){
		p_work->move_flg	= 0;
		return TRUE;
	} else {
		GetPosTblLiner( p_work->cp_tbl, p_work->fxcnt, p_x, p_y );
		p_work->fxcnt	+= p_work->fxcnt_add;
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *		【ランダム　BMP　塗りつぶし】
 *	@brief	BMPランダム塗りつぶしワーク作成
 *
 *	@param	heapID	ヒープID
 *
 *	@return	ワーク
 */
//-----------------------------------------------------------------------------
ENC_BMP_RND_FILL* ENC_BMP_RndFillAlloc( u32 heapID )
{
	ENC_BMP_RND_FILL* p_work;
	int i;

	p_work = sys_AllocMemory( heapID, sizeof(ENC_BMP_RND_FILL) );
	memset( p_work, 0, sizeof(ENC_BMP_RND_FILL) );

	return p_work;
}

//----------------------------------------------------------------------------
/**
 *		【ランダム　BMP　塗りつぶし】
 *	@brief	BMPランダム塗りつぶしワーク破棄
 *
 *	@param	p_work	ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_BMP_RndFillDelete( ENC_BMP_RND_FILL* p_work )
{
	sys_FreeMemoryEz( p_work );
}

//----------------------------------------------------------------------------
/**
 *		【ランダム　BMP　塗りつぶし】
 *	@brief	BMPランダム塗りつぶしエフェクト開始
 *
 *	@param	p_work	ワーク
 *	@param	start	１つのオブジェ発射タイミング
 *	@param	p_bmp	ビットマップ
 *	@param	col		カラー
 *
 *	@return
 */
//-----------------------------------------------------------------------------
void ENC_BMP_RndFillStart( ENC_BMP_RND_FILL* p_work, u8 start, GF_BGL_BMPWIN* p_bmp, u8 col )
{
	p_work->p_bmp		= p_bmp;
	p_work->col			= col;
	p_work->start_sync	= start;
	p_work->block_count = 0;
	p_work->wait		= 0;
	p_work->init_flg	= 1;

	ENC_InitNonRepeatRnd( &p_work->rnd, ENCOUNT_BLOCK_RND_OBJNUM );
}

//----------------------------------------------------------------------------
/**
 *		【ランダム　BMP　塗りつぶし】
 *	@brief	BMPランダム塗りつぶしメイン処理
 *
 *	@param	p_work	ワーク
 *
 *	@retval	TRUE	終了
 *	@retval FALSE	途中
 */
//-----------------------------------------------------------------------------
BOOL ENC_BMP_RndFillMain( ENC_BMP_RND_FILL* p_work )
{
	int i;
	u16 rnd;
	s16 left, top, right, bottom;
	s16 x, y;
	BOOL result;

	GF_ASSERT( p_work != NULL );

	//	初期化チェック
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	// 次々とFillしていく
	if( p_work->block_count < ENCOUNT_BLOCK_RND_OBJNUM ){
		p_work->wait --;
		if( p_work->wait <= 0 ){
			p_work->wait = p_work->start_sync;
			//	発射
			rnd	= ENC_GetNonRepeatRnd( &p_work->rnd );
			//	ランダムで座標を求める
			x		= (rnd % ENCOUNT_BLOCK_RND_X_NUM) * ENCOUNT_BLOCK_RND_WIDTH;
			y		= (rnd / ENCOUNT_BLOCK_RND_X_NUM) * ENCOUNT_BLOCK_RND_HEIGHT;
			//	中心座標を矩形座標に直す
			left	= x;
			top		= y;;
			right	= x + (ENCOUNT_BLOCK_RND_WIDTH/*/2*/);
			bottom	= y + (ENCOUNT_BLOCK_RND_HEIGHT/*/2*/);
			//	Fill
			ENC_BMP_Fill( p_work->p_bmp, top, bottom, left, right, p_work->col );
			p_work->block_count ++;
		}
	}

	//	終了チェック
	if( p_work->block_count >= ENCOUNT_BLOCK_RND_OBJNUM ) {
		p_work->init_flg = FALSE;
		return TRUE;
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	重複していないランダムを初期化
 *
 *	@param	p_work 初期化するワーク
 *	@param	max		ランダム最大値
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void ENC_InitNonRepeatRnd( ENC_NONREPEATRND_WORK *p_work, u32 max )
{
	int i;
	int rnd;
	u16	tmp;

	GF_ASSERT( NONREPEATRND_BUFF_MAX > max );	//	バッファオーバー

	//	初期化
	for( i = 0; i < max; i++ ) {
		p_work->tbl[i]	= i;
	}

	//	シャッフル
	for( i = 0; i < max - 1; i++ ) {
			rnd	= gf_rand() % max;
			tmp	= p_work->tbl[i];
			p_work->tbl[i]		= p_work->tbl[rnd];
			p_work->tbl[rnd]	= tmp;
	}

	p_work->idx	= 0;
	p_work->max	= max;
}

//----------------------------------------------------------------------------
/**
 *	@brief	重複していないランダムな値をとる
 *
 *	@param	p_work
 *
 *	@return	今までに重複していないランダムな値
 */
//-----------------------------------------------------------------------------
static u16 ENC_GetNonRepeatRnd( ENC_NONREPEATRND_WORK *p_work )
{
	u16	result	= p_work->tbl[ p_work->idx++ ];
	p_work->idx	= MATH_CLAMP( p_work->idx, 0, p_work->max );

	return result;
}

//----------------------------------------------------------------------------
/**
 *		【キャラ　BMP　塗りつぶし】
 *	@brief	CHRランダム塗りつぶしワーク作成
 *
 *	@param	heapID	ヒープID
 *	@param	chrIdx	読み込むキャラの番号
 *
 *	@return	ワーク
 */
//-----------------------------------------------------------------------------
ENC_BMP_CHR_FILL* ENC_BMP_ChrFillAlloc( u32 heapID, u32 chrIdx )
{
	ENC_BMP_CHR_FILL* p_work;
	int i;

	p_work = sys_AllocMemory( heapID, sizeof(ENC_BMP_CHR_FILL) );
	memset( p_work, 0, sizeof(ENC_BMP_CHR_FILL) );

	p_work->p_char	= ArcUtil_CharDataGet( ARC_ENCOUNTEFFECT, chrIdx, FALSE, &p_work->p_chardata, heapID );
	GF_ASSERT( p_work->p_char != NULL  );

	return p_work;
}

//----------------------------------------------------------------------------
/**
 *		【キャラ　BMP　塗りつぶし】
 *	@brief	CHRランダム塗りつぶしワーク削除
 *
 *	@param	ENC_BMP_CHR_FILL* p_work	削除するワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_BMP_ChrFillDelete( ENC_BMP_CHR_FILL* p_work )
{
	GF_ASSERT( p_work != NULL );

	//	キャラデータ破棄
	sys_FreeMemoryEz( p_work->p_char );
	sys_FreeMemoryEz( p_work );
}

//----------------------------------------------------------------------------
/**
 *		【キャラ　BMP　塗りつぶし】
 *	@brief	CHRランダム塗りつぶしエフェクト開始
 *
 *	@param	p_work	ワーク
 *	@param	start	１つのオブジェ発射タイミング
 *	@param	p_bmp	ビットマップ
 *	@param	col		カラー
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_BMP_ChrFillStart( ENC_BMP_CHR_FILL* p_work, u8 start, GF_BGL_BMPWIN* p_bmp, u8 col )
{
	GF_ASSERT( p_bmp != NULL );

	p_work->p_bmp		= p_bmp;
	p_work->col			= col;
	p_work->start_sync	= start;
	p_work->stamp_count = 0;
	p_work->wait		= 0;
	p_work->init_flg	= 1;

	ENC_InitNonRepeatRnd( &p_work->rnd, ENCOUNT_STAMP_CHR_PRESSNUM );
}

//----------------------------------------------------------------------------
/**
 *		【ランダム　BMP　塗りつぶし】
 *	@brief	BMPランダム塗りつぶしメイン処理
 *
 *	@param	p_work	ワーク
 *
 *	@retval	TRUE	終了
 *	@retval FALSE	途中
 */
//-----------------------------------------------------------------------------
BOOL ENC_BMP_ChrFillMain( ENC_BMP_CHR_FILL* p_work )
{
	int i;
	u16 rnd;
	s16 x, y;
	BOOL result;

	GF_ASSERT( p_work != NULL );

	//	初期化チェック
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	// 次々とFillしていく
	if( p_work->stamp_count < ENCOUNT_STAMP_CHR_PRESSNUM ){
		p_work->wait --;
		if( p_work->wait <= 0 ){
			p_work->wait = p_work->start_sync;
			//	ランダム計算
			rnd	= ENC_GetNonRepeatRnd( &p_work->rnd );
			//	ランダムで座標を求める
			x		= (rnd % ENCOUNT_STAMP_RND_X_NUM) * ENCOUNT_STAMP_RND_WIDTH;
			y		= (rnd / ENCOUNT_STAMP_RND_X_NUM) * ENCOUNT_STAMP_RND_HEIGHT;
			//	Stamp
			ENC_BMP_StampCharacter( p_work->p_bmp, p_work->p_chardata, x, y, p_work->col );

			p_work->stamp_count ++;
		}
	}

	//	終了チェック
	if( p_work->stamp_count >= ENCOUNT_STAMP_CHR_PRESSNUM ) {
		p_work->init_flg = FALSE;
		return TRUE;
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	BMPに対して、点をうつ
 *
 *	@param	GF_BGL_BMPWIN* p_bmp	書き込み先BMP
 *	@param	x						書き込み先座標
 *	@param	y						書き込み先座標
 *	@param	col						書き込む色
 *
 *	@return
 */
//-----------------------------------------------------------------------------
static void ENC_BMP_Point( GF_BGL_BMPWIN* p_bmp, s32 x, s32 y, u8 col )
{
	if( 0 <= x & x < 256
	 & 0 <= y & y < 192 ) {
		// ビットマップ塗りつぶし
		GF_BGL_BmpWinFill( p_bmp, col, x, y, 1, 1 );
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	2DMappingModeの16色キャラクターバッファから2次元座標でドットを取り出す。
 *			（バッファ内部はキャラクター座標（1キャラごと）に入っているため）
 *
 *	@param	cp_chardata				キャラクターのデータ
 *	@param	x						ドットのX座標
 *	@param	y						ドットのY座標
 *
 *	@return	ドット（パレット番号が格納されている）
 */
//-----------------------------------------------------------------------------
static u8 ENC_CHR_GetDot16( const NNSG2dCharacterData *cp_chardata, u16 x, u16 y )
{

#if 0
	static const int CHARA_SIDE_DOT	= 8;				//	キャラ一辺のドット数8*8
	static const int DOT_BIT_NUM	= 4;				//	1ドット4ビット
	static const int CHARA_IN_DOTNUM= CHARA_SIDE_DOT * CHARA_SIDE_DOT;	//	1キャラ64ドット

	int chr_x, chr_y;	//	キャラ座標
	int dot_x, dot_y;	//	ドット座標
	static const int U32_IN_DOTNUM	= 32/DOT_BIT_NUM;	//	32bitの中に何ドットあるか

	const u32	*cp_buff	= cp_chardata->pRawData;
	const u32	*cp_chara_pos_data;
	u8			dot;
	u32			buff_pos;

	GF_ASSERT( cp_chardata->mapingType == GX_OBJVRAMMODE_CHAR_2D );
	GF_ASSERT( cp_chardata->pixelFmt == GX_TEXFMT_PLTT16 );

	//	ドット座標をキャラクタ座標に
	chr_x		= x / CHARA_SIDE_DOT;
	chr_y		= y / CHARA_SIDE_DOT;

	//	キャラクタの先頭バッファを取得
	cp_chara_pos_data	= cp_buff + (chr_y * cp_chardata->W + chr_x)*CHARA_IN_DOTNUM/U32_IN_DOTNUM;

	//	１キャラ内での座標でドットを取り出す
	dot_x		= x % CHARA_SIDE_DOT;
	dot_y		= y % CHARA_SIDE_DOT;
	buff_pos	= dot_y * CHARA_SIDE_DOT / U32_IN_DOTNUM/* + dot_x / U32_IN_DOTNUM*/;	//１つのバッファにドットが8つ入っているため

	return ( cp_chara_pos_data[ buff_pos ] >> (dot_x%U32_IN_DOTNUM)*DOT_BIT_NUM) & 0xF;
#elif 0
	static const int CHARA_SIDE_DOT	= 8;				//	キャラ一辺のドット数8*8
	static const int DOT_BIT_NUM	= 4;				//	1ドット4ビット
	static const int CHARA_IN_DOTNUM= CHARA_SIDE_DOT * CHARA_SIDE_DOT;	//	1キャラ64ドット

	int chr_x, chr_y;	//	キャラ座標
	int dot_x, dot_y;	//	ドット座標
	//	CPUは32ビットだが、メインメモリバス幅が16ビットしかないため、
	//	16ビットで計算した方が速いらしい
	static const int U16_IN_DOTNUM	= 16/DOT_BIT_NUM;	//	16bitの中に何ドットあるか

	const u16	*cp_buff	= cp_chardata->pRawData;
	const u16	*cp_chara_pos_data;
	u16			buff_pos;

	GF_ASSERT( cp_chardata->mapingType == GX_OBJVRAMMODE_CHAR_2D );
	GF_ASSERT( cp_chardata->pixelFmt == GX_TEXFMT_PLTT16 );

	//	ドット座標をキャラクタ座標に
	chr_x		= x / CHARA_SIDE_DOT;
	chr_y		= y / CHARA_SIDE_DOT;

	//	キャラクタの先頭バッファを取得
	cp_chara_pos_data	= cp_buff + (chr_y * cp_chardata->W + chr_x)*16/*CHARA_IN_DOTNUM/U16_IN_DOTNUM*/;

	//	１キャラ内での座標でドットを取り出す
	dot_x		= x % CHARA_SIDE_DOT;
	dot_y		= y % CHARA_SIDE_DOT;
	buff_pos	= dot_y * 2/*CHARA_SIDE_DOT / U16_IN_DOTNUM*/ + dot_x / U16_IN_DOTNUM;	//１つのバッファにドットが8つ入っているため

	return ( cp_chara_pos_data[ buff_pos ] >> (dot_x%U16_IN_DOTNUM)*DOT_BIT_NUM) & 0xF;

#else
//	const u16	*cp_buff	= cp_chardata->pRawData;
//	const u16	*cp_chara_pos_data;

	//	上の式を高速化
	//cp_chara_pos_data	= cp_buff + (((y >> 3) * cp_chardata->W + (x >> 3) ) << 4);
//	return ( cp_chara_pos_data[ ((y&7) << 1) + ((x&7) >> 2) ] >> (((x&7)&3)<<2)) & 0xF;

	//	さらに代入をさけて高速化
	return (*((((u16*)cp_chardata->pRawData) + (((y >> 3) * cp_chardata->W + (x >> 3) ) << 4)
			+ (((y&7) << 1) + ((x&7) >> 2)))) >> (((x&7)&3)<<2) ) & 0xF;



#endif
}

//----------------------------------------------------------------------------
/**
 *	@brief	2DMappingModeの16色キャラクターバッファへ2次元座標でドットを入れる
 *			（バッファ内部はキャラクター座標（1キャラごと）に入っているため）
 *
 *	@param	p_chardata				キャラクターのデータ
 *	@param	dot						ドットのデータ（パレット番号）
 *	@param	x						ドットのX座標
 *	@param	y						ドットのY座標
 *
 */
//-----------------------------------------------------------------------------
static void ENC_CHR_SetDot16( NNSG2dCharacterData *p_chardata, u8 dot, u16 x, u16 y )
{
	static const int CHARA_SIDE_DOT	= 8;				//	キャラ一辺のドット数8*8
	static const int DOT_BIT_NUM	= 4;				//	1ドット4ビット
	static const int U32_IN_DOTNUM	= 32/DOT_BIT_NUM;	//	32bitの中に何ドットあるか
	static const int CHARA_IN_DOTNUM= CHARA_SIDE_DOT * CHARA_SIDE_DOT;	//	1キャラ64ドット

	static const u32 BIT_MASK_TBL[]	=  {
		0xFFFFFFF0, 0xFFFFFF0F, 0xFFFFF0FF, 0xFFFF0FFF,
		0xFFF0FFFF, 0xFF0FFFFF, 0xF0FFFFFF, 0x0FFFFFFF,
	};

	int chr_x, chr_y;	//	キャラ座標
	int dot_x, dot_y;	//	ドット座標
	u32 *p_buff		= p_chardata->pRawData;
	u32	*cp_chara_pos_data;
	u32	buff_pos;

	//	ドット座標をキャラクタ座標に
	chr_x		= x / CHARA_SIDE_DOT;
	chr_y		= y / CHARA_SIDE_DOT;

	//	キャラクタの先頭バッファを取得
	buff_pos	= (chr_y * p_chardata->W + chr_x)*8;
	cp_chara_pos_data	= p_buff + buff_pos;

	//	１キャラ内での座標でドットを取り出す
	dot_x		= x % CHARA_SIDE_DOT;
	dot_y		= y % CHARA_SIDE_DOT;
	buff_pos	= dot_y * CHARA_SIDE_DOT / U32_IN_DOTNUM/* + dot_x / U32_IN_DOTNUM*/;	//１つのバッファにドットが8つ入っているため
	cp_chara_pos_data[ buff_pos ]	&= BIT_MASK_TBL[dot_x%U32_IN_DOTNUM];
	cp_chara_pos_data[ buff_pos ]	|= dot << (dot_x%U32_IN_DOTNUM*DOT_BIT_NUM);

}


//----------------------------------------------------------------------------
/**
 *	@brief	BMPに対し、他のキャラクタの絵を書き込む（スタンプする）
 *			（ただし2DMappingModeのキャラクターに限る）
 *
 *	@param	GF_BGL_BMPWIN* p_bmp	書き込み先BMP
 *	@param	*cp_chardata			書き込み元キャラクター
 *	@param	x						書き込み先座標（BMPのこの座標を中心に元キャラクタを書き込みます）
 *	@param	y						書き込み先座標
 *	@param	col						書き込む色（この色に変換されます）
 *
 *	@return
 */
//-----------------------------------------------------------------------------
static void ENC_BMP_StampCharacter( GF_BGL_BMPWIN* p_bmp, const NNSG2dCharacterData *cp_chardata, s16 x, s16 y, u8 col )
{
	static const int CHARA_SIDE_DOT	= 8;				//	キャラ一辺のドット数8*8
	int i, j;
	int w, h;
	u8	dot;

	GF_ASSERT( cp_chardata->mapingType == GX_OBJVRAMMODE_CHAR_2D );

	//	中心座標に変換
	x	-= cp_chardata->W*CHARA_SIDE_DOT/2;
	y	-= cp_chardata->H*CHARA_SIDE_DOT/2;

	h	= cp_chardata->H * CHARA_SIDE_DOT;
	w	= cp_chardata->W * CHARA_SIDE_DOT;
	for( i = 0; i < h; i++ ) {
		for( j = 0; j < w; j++ ) {	//	ドットごとにサーチ
			dot	= ENC_CHR_GetDot16( cp_chardata, j, i );

			//	バッファの中の何番目のドットか
			if( dot )	{	//	透過色ではないとき書き込み
				ENC_BMP_Point( p_bmp, x+j, y+i, col );
			}
		}
	}


}

//----------------------------------------------------------------------------
/**
 *	@brief	指定距離内でn回書き込む
 *			（素早い速度で移動すると、途切れたように張られるので、
 *			始点から終点まで同シンク内で何回はるか指定し、書き込む関数）
 *
 *	@param	GF_BGL_BMPWIN* p_bmp	書き込み先BMP
 *	@param	NNSG2dCharacterData *cp_chardata	書き込み元キャラクター
 *	@param	s_x			始点
 *	@param	s_y			始点
 *	@param	e_x			終点
 *	@param	e_y			終点
 *	@param	num			何回Stampするか
 *	@param	col			色
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void ENC_BMP_StampCharacterCont( GF_BGL_BMPWIN* p_bmp, const NNSG2dCharacterData *cp_chardata, s16 s_x, s16 s_y, s16 e_x, s16 e_y, u8 num, u8 col )
{
	int i;
	s16 x, y;
	fx32 pos;

	for( i = 0; i < num; i++ ) {
		pos		= FX32_CONST(i) / num;
		LinerRatio( s_x, s_y, e_x, e_y, pos, &x, &y );
		ENC_BMP_StampCharacter( p_bmp, cp_chardata, x, y, col );
	}
}

//----------------------------------------------------------------------------
/**
 *		【BMP　ブラシ　塗りつぶし】
 *	@brief	ワーク作成
 *
 *	@param	heapID	ヒープID
 *	@param	chrIdx	読み込むキャラの番号
 *
 *	@return	ワーク
 */
//-----------------------------------------------------------------------------
ENC_BMP_CHR_BRUSH* ENC_BMP_ChrBrushAlloc( u32 heapID, u32 chrIdx )
{
	ENC_BMP_CHR_BRUSH* p_work;
	int i;

	p_work = sys_AllocMemory( heapID, sizeof(ENC_BMP_CHR_BRUSH) );
	memset( p_work, 0, sizeof(ENC_BMP_CHR_BRUSH) );

	p_work->p_char	= ArcUtil_CharDataGet( ARC_ENCOUNTEFFECT, chrIdx, FALSE, &p_work->p_chardata, heapID );
	GF_ASSERT( p_work->p_char != NULL  );

	return p_work;
}

//----------------------------------------------------------------------------
/**
 *		【BMP　ブラシ塗りつぶし】
 *	@brief	ワーク削除
 *
 *	@param	ENC_BMP_CHR_BRUSH* p_work	削除するワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_BMP_ChrBrushDelete( ENC_BMP_CHR_BRUSH *p_work )
{
	GF_ASSERT( p_work != NULL );

	//	キャラデータ破棄
	sys_FreeMemoryEz( p_work->p_char );
	sys_FreeMemoryEz( p_work );
}

//----------------------------------------------------------------------------
/**
 *	@brief	画面端の点を取る
 *
 *	@param	s16 now		現在の跳ね返り点
 *	@param	chr_w		キャラの幅
 *	@param	*p_x		[out]点の座標
 *	@param	*p_y		[out]点の座標
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void ENC_BMP_BRUSH_GetDispEdge( u8 dir, s16 now, u16 chr_w, s16 *p_x, s16 *p_y )
{
	const int DISP_DIV_WIDTH_POINT	= ENC_BMP_CHR_BRUSH_RANGE_WIDTH / chr_w;
	const int DISP_DIV_HEIGHT_POINT	= ENC_BMP_CHR_BRUSH_RANGE_HEIGHT / chr_w;

	//	偶数なら上と右、奇数なら左と下
	if( dir == 1 ) {
		if( now < DISP_DIV_WIDTH_POINT ) {	//	上
			*p_x	= ENC_BMP_CHR_BRUSH_RANGE_WIDTH_S + chr_w * now;
			*p_y	= ENC_BMP_CHR_BRUSH_RANGE_HEIGHT_S;
		}else if ( now == DISP_DIV_WIDTH_POINT ) {
			*p_x	= ENC_BMP_CHR_BRUSH_RANGE_WIDTH_E;
			*p_y	= ENC_BMP_CHR_BRUSH_RANGE_HEIGHT_S;
		}else{	//	右
			*p_x	= ENC_BMP_CHR_BRUSH_RANGE_WIDTH_E;
			*p_y	= ENC_BMP_CHR_BRUSH_RANGE_HEIGHT_S + chr_w * (now-DISP_DIV_WIDTH_POINT);
		}
	}else{
		if( now < DISP_DIV_HEIGHT_POINT ) {	//	左
			*p_x	= ENC_BMP_CHR_BRUSH_RANGE_WIDTH_S;
			*p_y	= ENC_BMP_CHR_BRUSH_RANGE_HEIGHT_S + chr_w * now;
		}else if(now == DISP_DIV_HEIGHT_POINT ) {
			*p_x	= ENC_BMP_CHR_BRUSH_RANGE_WIDTH_S;
			*p_y	= ENC_BMP_CHR_BRUSH_RANGE_HEIGHT_E;
		}else{	//下
			*p_x	= ENC_BMP_CHR_BRUSH_RANGE_WIDTH_S + chr_w * (now-DISP_DIV_HEIGHT_POINT);
			*p_y	= ENC_BMP_CHR_BRUSH_RANGE_HEIGHT_E;
		}
	}
}


//----------------------------------------------------------------------------
/**
 *	@brief	跳ね返り始点、終点を受け取る
 *
 *	@param	s16 now	現在の跳ね返り番号
 *	@param	chr_w	キャラ幅
 *	@param	*p_sx	[out]跳ね返り始点
 *	@param	*p_sy	[out]跳ね返り始点
 *	@param	*p_ex	[out]跳ね返り点終端
 *	@param	*p_ey	[out]跳ね返り点終端
 *
 *	@return	跳ね返り点を回り終えたか
 */
//-----------------------------------------------------------------------------
static BOOL ENC_BMP_BRUSH_GetReflexPoint( u8 *p_flg, s16 now, u16 chr_w, s16 *p_sx, s16 *p_sy, s16 *p_ex, s16 *p_ey )
{

	const int DISP_DIV_WIDTH_POINT	= ENC_BMP_CHR_BRUSH_RANGE_WIDTH / chr_w;
	const int DISP_DIV_HEIGHT_POINT	= ENC_BMP_CHR_BRUSH_RANGE_HEIGHT / chr_w;

	//	終了条件
	if( now >=  (DISP_DIV_WIDTH_POINT + DISP_DIV_HEIGHT_POINT) ) {
		return TRUE;
	}

	//	始点
	ENC_BMP_BRUSH_GetDispEdge( *p_flg, now, chr_w, p_sx, p_sy );

	*p_flg	^=	1;	//	反転
	//	終点
	ENC_BMP_BRUSH_GetDispEdge( *p_flg, now+1, chr_w, p_ex, p_ey );

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *		【BMP　ブラシ　塗りつぶし
 *	@brief	エフェクト開始
 *
 *	@param	ENC_BMP_CHR_BRUSH* p_work	ワーク
 *	@param	piece_sync					ひとつの直線を描くシンク
 *	@param	chr_w						線と線の幅
 *	@param	p_bmp						書き込むBMP
 *	@param	col							色
 *
 *	@return:v
 */
//-----------------------------------------------------------------------------
void ENC_BMP_ChrBrushStart( ENC_BMP_CHR_BRUSH *p_work, u8 piece_sync, u16 chr_w, GF_BGL_BMPWIN* p_bmp, u8 col )
{
	s16 s_x, e_x;
	s16 s_y, e_y;
	GF_ASSERT( p_bmp != NULL );

	p_work->reflex_point_now	= 1;
	p_work->piece_sync	= piece_sync;
	p_work->chr_w		= chr_w;
	p_work->dir_flg		= 1;
	p_work->p_bmp		= p_bmp;
	p_work->col			= col;
	p_work->init_flg	= 1;

	ENC_BMP_BRUSH_GetReflexPoint( &p_work->dir_flg, p_work->reflex_point_now, p_work->chr_w, &s_x, &s_y, &e_x, &e_y  );

	p_work->src_x		= s_x;
	p_work->src_y		= s_y;

	ENC_MoveReq( &p_work->move_x, s_x, e_x, p_work->piece_sync );
	ENC_MoveReq( &p_work->move_y, s_y, e_y, p_work->piece_sync );
}

//----------------------------------------------------------------------------
/**
 *		【BMP　ブラシ　塗りつぶし】
 *	@brief	BMPランダム塗りつぶしメイン処理
 *
 *	@param	p_work	ワーク
 *
 *	@retval	TRUE	終了
 *	@retval FALSE	途中
 */
//-----------------------------------------------------------------------------
BOOL ENC_BMP_ChrBrushMain( ENC_BMP_CHR_BRUSH *p_work )
{
	int i;
	s16 x, y;
	BOOL	result	= FALSE;

	GF_ASSERT( p_work != NULL );

	//
	//	跳ね返り点を最初から最後まで求め、
	//	順番に線を引いていく。
	//
	//
	//
	//


	//	初期化チェック
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	result	= ENC_MoveMain( &p_work->move_x);
	result	|= ENC_MoveMain( &p_work->move_y);

	if( result ) {
		s16 s_x, e_x;
		s16 s_y, e_y;
		//一片が終了したら
		//次の片を
		p_work->reflex_point_now++;
		//跳ね返り点がなかったらおわり
		result	= ENC_BMP_BRUSH_GetReflexPoint( &p_work->dir_flg, p_work->reflex_point_now, p_work->chr_w, &s_x, &s_y, &e_x, &e_y );

		if( result ) {
		//	p_work->init_flg = FALSE;
			return WIPE_SYS_EndCheck();
		}

		ENC_MoveReq( &p_work->move_x, s_x, e_x, p_work->piece_sync );
		ENC_MoveReq( &p_work->move_y, s_y, e_y, p_work->piece_sync );


#ifdef ENCOUNT_BRUSH_FADE_DIV
	{
		const int DISP_DIV_WIDTH_POINT	= ENC_BMP_CHR_BRUSH_RANGE_WIDTH / p_work->chr_w;
		const int DISP_DIV_HEIGHT_POINT	= ENC_BMP_CHR_BRUSH_RANGE_HEIGHT / p_work->chr_w;
		int fade_start_reflex_point	= ((DISP_DIV_WIDTH_POINT +DISP_DIV_HEIGHT_POINT) * ENCOUNT_BRUSH_FADE_DIV) >> FX32_SHIFT;
		int fade_sync	= (DISP_DIV_WIDTH_POINT + DISP_DIV_HEIGHT_POINT) - fade_start_reflex_point;

		if( p_work->reflex_point_now == fade_start_reflex_point )  {
			WIPE_SYS_Start( WIPE_PATTERN_M, WIPE_TYPE_FADEOUT, WIPE_TYPE_FADEOUT, WIPE_FADE_BLACK, fade_sync, fade_sync, HEAPID_FIELD );
			NAGIHASHI_PRINT( "FADESTART\n" );
		}
		NAGIHASHI_PRINT( "FADE NOW:%d START:%d DIV:%d POINT:%d\n",p_work->reflex_point_now, fade_start_reflex_point, ENCOUNT_BRUSH_FADE_DIV, (DISP_DIV_WIDTH_POINT + DISP_DIV_HEIGHT_POINT) );
	}
#endif //	ENCOUNT_BRUSH_FADE_DIV != 0



	}

	// ブラシ塗りつぶし処理

	ENC_BMP_StampCharacterCont( p_work->p_bmp, p_work->p_chardata,
			p_work->src_x, p_work->src_y, p_work->move_x.x, p_work->move_y.x, ENC_BMP_CHR_BRUSH_STAMP_CNT, p_work->col );
	p_work->src_x	= p_work->move_x.x;
	p_work->src_y	= p_work->move_y.x;

	return FALSE;
}




//----------------------------------------------------------------------------
/**
 *		【BMP　手書きブラシ塗りつぶし】
 *	@brief	ワーク作成
 *
 *	@param	heapID	ヒープID
 *	@param	chrIdx	読み込むキャラの番号
 *
 *	@return	ワーク
 */
//-----------------------------------------------------------------------------
ENC_BMP_HAND_BRUSH* ENC_BMP_HandBrushAlloc( u32 heapID, u32 chrIdx )
{
	ENC_BMP_HAND_BRUSH* p_work;
	int i;

	p_work = sys_AllocMemory( heapID, sizeof(ENC_BMP_HAND_BRUSH) );
	memset( p_work, 0, sizeof(ENC_BMP_HAND_BRUSH) );

	p_work->p_hand	= ENC_HandDrawAlloc( heapID );
	p_work->p_char	= ArcUtil_CharDataGet( ARC_ENCOUNTEFFECT, chrIdx, FALSE, &p_work->p_chardata, heapID );
	GF_ASSERT( p_work->p_char != NULL  );

	return p_work;
}

//----------------------------------------------------------------------------
/**
 *		【BMP　手書きブラシ塗りつぶし】
 *	@brief	ワーク削除
 *
 *	@param	ENC_BMP_HAND_BRUSH* p_work	削除するワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_BMP_HandBrushDelete( ENC_BMP_HAND_BRUSH *p_work )
{
	GF_ASSERT( p_work != NULL );

	//	キャラデータ破棄
	sys_FreeMemoryEz( p_work->p_char );

	ENC_HandDrawDelete( p_work->p_hand );
	sys_FreeMemoryEz( p_work );
}


//----------------------------------------------------------------------------
/**
 *		【BMP　手書きブラシ塗りつぶし
 *	@brief	エフェクト開始
 *
 *	@param	ENC_BMP_HAND_BRUSH* p_work	ワーク
 *	@param	x				開始座標
 *	@param	y				開始座標
 *	@param  spd				速さ
 *	@param	start_angle		開始角度
 *	@param	turn_angle		折り返し角度
 *	@param	p_bmp			書き込むBMP
 *	@param	col				色
 *
 *	@return
 */
//-----------------------------------------------------------------------------
void ENC_BMP_HandBrushStart( ENC_BMP_HAND_BRUSH *p_work, GF_BGL_BMPWIN* p_bmp, u8 col )
{
#if 0
	static const ENC_HAND_DRAW_POS_TBL enc_draw_pos_tbl[] = {
		{ 0, 0},
		{ 30, 9 },
        { 9, 66},
        { 116, 9},
        { 9, 97},
        { 187, 8},
        { 10, 120},
        { 231, 9},
        { 9, 160},
        { 245, 36},
        { 41, 182},
        { 246, 73},
        { 116, 185},
        { 248, 126},
        { 188, 185},
        { 248, 184},
        { ENC_HAND_DRAW_POS_TBL_END, ENC_HAND_DRAW_POS_TBL_END },
	};
#else

	#include "d_nagi.h"
	static const ENC_HAND_DRAW_POS_TBL enc_draw_pos_tbl[] = {
        { 117, 49},
        { 76, 77},
        { 71, 130},
        { 123, 159},
        { 157, 129},
        { 155, 74},
        { 117, 49},
        { ENC_HAND_DRAW_POS_TBL_END, ENC_HAND_DRAW_POS_TBL_END },
	};

#endif

	GF_ASSERT( p_bmp != NULL );

	p_work->p_bmp		= p_bmp;
	p_work->col			= col;
	p_work->init_flg	= 1;

//	ENC_HandDrawStart( p_work->p_hand, g_debug_enc_draw_pos_tbl, 30 );
	ENC_HandDrawStart( p_work->p_hand, enc_draw_pos_tbl, 30 );
	//	1回に2座標ほしいので、最初に1回動かす
	ENC_HandDrawGetPosMain( p_work->p_hand, &p_work->src_x, &p_work->src_y );
	ENC_BMP_StampCharacter( p_work->p_bmp, p_work->p_chardata, p_work->src_x, p_work->src_y, p_work->col );
}

//----------------------------------------------------------------------------
/**
 *		【BMP　手書きブラシ塗りつぶし】
 *	@brief	BMPランダム塗りつぶしメイン処理
 *
 *	@param	p_work	ワーク
 *
 *	@retval	TRUE	終了
 *	@retval FALSE	途中
 */
//-----------------------------------------------------------------------------
BOOL ENC_BMP_HandBrushMain( ENC_BMP_HAND_BRUSH *p_work )
{
	s16 x, y;

	GF_ASSERT( p_work != NULL );

	//	初期化チェック
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	//	終了チェック
	if( ENC_HandDrawGetPosMain( p_work->p_hand, &x, &y ) ) {
		p_work->init_flg = FALSE;
		return TRUE;
	}

	ENC_BMP_StampCharacterCont( p_work->p_bmp, p_work->p_chardata,
			p_work->src_x, p_work->src_y, x, y, 12, p_work->col );
	p_work->src_x	= x;
	p_work->src_y	= y;


	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	位置テーブルから線形補間しつつ、任意のタイミングの点を取得
 *
 *	@param	const ENC_HAND_DRAW_POS_TBL cp_tbl[]
 *	@param	fxcnt
 *	@param	*p_out_x
 *	@param	*p_out_y
 *
 *	@return
 */
//-----------------------------------------------------------------------------
static void GetPosTblLiner( const ENC_HAND_DRAW_POS_TBL cp_tbl[], fx32 fxcnt,s16 *p_out_x, s16 *p_out_y )
{
	int start_pos, end_pos;
	fx32 fxdec;

	start_pos		= fxcnt >> FX32_SHIFT;
	fxdec				= fxcnt - FX32_CONST(start_pos);
	end_pos			= start_pos+1;

	LinerRatio( cp_tbl[start_pos].x, cp_tbl[start_pos].y, cp_tbl[end_pos].x, cp_tbl[end_pos].y,
			fxdec, p_out_x, p_out_y );
}

//----------------------------------------------------------------------------
/**
 *	@brief	2点間の距離を比で求める
 *
 *	@param	u8 s_x		始点X
 *	@param	s_y			始点Y
 *	@param	e_x			終点X
 *	@param	e_y			終点Y
 *	@param	pos			0〜1までの値
 *	@param	*p_out_x	取得X
 *	@param	*p_out_y	取得Y
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void LinerRatio( s16 s_x, s16 s_y, s16 e_x, s16 e_y, fx32 pos, s16 *p_out_x, s16 *p_out_y )
{
	if( p_out_x != NULL ) {
		*p_out_x	= (((e_x - s_x) * pos) >> FX32_SHIFT) + s_x;
	}
	if( p_out_y != NULL ) {
		*p_out_y	= (((e_y - s_y) * pos) >> FX32_SHIFT) + s_y;
	}
}

//----------------------------------------------------------------------------
/**
 *	【パタパタシステム】
 *	@brief	システム作成
 *
 *	@param	u32 heapID	ヒープID
 *
 *	@return	ワークハンドル
 */
//-----------------------------------------------------------------------------
ENC_BMP_PATAPATA_FILL* ENC_BMP_PatapataFillAlloc( u32 heapID )
{
	int i;
	ENC_BMP_PATAPATA_FILL	*p_work;
	p_work = sys_AllocMemory( heapID, sizeof(ENC_BMP_PATAPATA_FILL) );
	memset( p_work, 0, sizeof(ENC_BMP_PATAPATA_FILL) );

	for( i = 0; i <ENCOUNT_PATAPATA_FILL_OBJNUM; i++ ) {
		p_work->p_fill[i]	= ENC_BMP_FillSpreadAlloc( heapID );
	}

	return p_work;
}

//----------------------------------------------------------------------------
/**
 *	【パタパタシステム】
 *	@brief	システム破棄
 *
 *	@param	ENC_BMP_PATAPATA_FILL *p_work 破棄するワークハンドル
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_BMP_PatapataFillDelete( ENC_BMP_PATAPATA_FILL *p_work )
{
	int i;
	GF_ASSERT( p_work != NULL );

	for( i = 0; i <ENCOUNT_PATAPATA_FILL_OBJNUM; i++ ) {
		ENC_BMP_FillSpreadDelete( p_work->p_fill[i] );
	}
	sys_FreeMemoryEz( p_work );
}

//----------------------------------------------------------------------------
/**
 * 【パタパタシステム】
 *	@brief	システム実行
 *
 *	@param	ENC_BMP_RND_FILL* p_work	実行するワークハンドル
 *	@param	one_start_sync				一辺の開始シンク
 *	@param	one_fill_sync				一辺の塗りつぶしシンク
 *	@param	p_bmp						書き込むBMPWIN
 *	@param	col							書き込む色
 *	@param	b_morning					朝夜フラグ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_BMP_PatapataFillStart( ENC_BMP_PATAPATA_FILL* p_work, u8 one_start_sync, u8 one_fill_sync, GF_BGL_BMPWIN* p_bmp, u8 col, BOOL b_morning )
{
	GF_ASSERT( p_bmp != NULL );

	p_work->p_bmp			= p_bmp;
	p_work->col				= col;
	p_work->one_start_sync	= one_start_sync;
	p_work->one_fill_sync	= one_fill_sync;
	p_work->block_count		= 0;
	p_work->block_end_count	= 0;
	p_work->wait			= one_start_sync;
	p_work->init_flg		= 1;
	p_work->b_morning		= b_morning;
}

//----------------------------------------------------------------------------
/**
 * 【パタパタシステム】
 *	@brief	システムメイン処理
 *
 *	@param	ENC_BMP_PATAPATA_FILL *p_work	実行するワークハンドル
 *
 *	@retval	TRUE	処理完了
 *	@retval	FALSE	処理継続中
 */
//-----------------------------------------------------------------------------
BOOL ENC_BMP_PatapataFillMain( ENC_BMP_PATAPATA_FILL *p_work )
{
	int x, y;
	int index;
	int i;
	BOOL result;

	GF_ASSERT( p_work != NULL );

	//	未初期化時は終了
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	// 開始部
	if( p_work->block_count < ENCOUNT_PATAPATA_FILL_OBJNUM/2 ){
		p_work->wait --;
		if( p_work->wait <= 0 ){
			p_work->wait = p_work->one_start_sync;

			//	1つ目発射
			if( p_work->b_morning ) {
				index	= ENCOUNT_PATAPATA_FILL_MoveParam_Order( p_work->block_count );
			}else{
				index	= ENCOUNT_PATAPATA_FILL_MoveParam_Order_N( p_work->block_count );
			}

			x		= (index % ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_WIDTH + ENCOUNT_PATAPATA_FILL_WIDTH/2;	//	中心座標なので+WIDTH/2
			y		= (index / ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_HEIGHT + ENCOUNT_PATAPATA_FILL_HEIGHT/2;
			// 発射
			ENC_BMP_FillSpreadStart(
					p_work->p_fill[ index ],
					x, y,
					p_work->one_fill_sync, p_work->p_bmp,
					0, ENCOUNT_PATAPATA_FILL_HEIGHT,
					ENCOUNT_PATAPATA_FILL_WIDTH, ENCOUNT_PATAPATA_FILL_HEIGHT,
					p_work->col );

			//	2つ目発射
			if( p_work->b_morning ) {
				index	= ENCOUNT_PATAPATA_FILL_MoveParam_Reverse( p_work->block_count );
			}else{
				index	= ENCOUNT_PATAPATA_FILL_MoveParam_Reverse_N( p_work->block_count );
			}

			x		= (index % ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_WIDTH + ENCOUNT_PATAPATA_FILL_WIDTH/2;
			y		= (index / ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_HEIGHT + ENCOUNT_PATAPATA_FILL_HEIGHT/2;
			ENC_BMP_FillSpreadStart(
					p_work->p_fill[ index ],
					x, y,
					p_work->one_fill_sync, p_work->p_bmp,
					0, ENCOUNT_PATAPATA_FILL_HEIGHT,
					ENCOUNT_PATAPATA_FILL_WIDTH, ENCOUNT_PATAPATA_FILL_HEIGHT,
					p_work->col );

			p_work->block_count ++;
		}
	}


	// 動さ部
	for( i=p_work->block_end_count; i<p_work->block_count; i++ ){
		int order_idx;
		int reverse_idx;
		if( p_work->b_morning ) {
			order_idx	= ENCOUNT_PATAPATA_FILL_MoveParam_Order( i );
			reverse_idx	= ENCOUNT_PATAPATA_FILL_MoveParam_Reverse( i );
		}else{
			order_idx	= ENCOUNT_PATAPATA_FILL_MoveParam_Order_N( i );
			reverse_idx	= ENCOUNT_PATAPATA_FILL_MoveParam_Reverse_N( i );
		}
		result = ENC_BMP_FillSpreadMain( p_work->p_fill[order_idx] );
		result |= ENC_BMP_FillSpreadMain( p_work->p_fill[reverse_idx] );
		if( result == TRUE ){
			p_work->block_end_count++;
		}
	}

	// 全動さ終了チェック
	if( (p_work->block_end_count >= ENCOUNT_PATAPATA_FILL_OBJNUM/2) &&
		(result == TRUE) ){
		p_work->init_flg = FALSE;
		return TRUE;
	}

	return FALSE;
}
BOOL ENC_BMP_PatapataFillMain1( ENC_BMP_PATAPATA_FILL *p_work )
{
	int x, y;
	int index;
	int i;
	BOOL result;
	int w, h;

	static const struct {
		u8 idx;
		u8 wh;	//	縦なら1横なら0
	}ENCOUNT_PATAPATA_FILL_MoveParam1[ ENCOUNT_PATAPATA_FILL_OBJNUM/2] = {	// 出てくる順番テーブル
		{0,0},  {1,0},  {2,0},  {3,0},  {4,0},  {5,0},  {6,0},  {7,1},
		{15,1}, {23,1}, {31,1}, {39,0}, {38,0}, {37,0}, {36,0}, {35,0},
		{34,0}, {33,1}, {25,1}, {17,0}, {18,0}, {19,0}, {20,0}, {21,0},
	};

#define ENCOUNT_PATAPATA_FILL_MoveParam_Order1(x)	(ENCOUNT_PATAPATA_FILL_MoveParam1[ x ].idx)
#define ENCOUNT_PATAPATA_FILL_MoveParam_Reverse1(x) (ENCOUNT_PATAPATA_FILL_OBJNUM - 1 - ENCOUNT_PATAPATA_FILL_MoveParam1[ x ].idx)


	GF_ASSERT( p_work != NULL );

	//	未初期化時は終了
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	// 開始部
	if( p_work->block_count < ENCOUNT_PATAPATA_FILL_OBJNUM/2 ){
		p_work->wait --;
		if( p_work->wait <= 0 ){
			p_work->wait = p_work->one_start_sync;

			//	1つ目発射
			index	= ENCOUNT_PATAPATA_FILL_MoveParam_Order1( p_work->block_count );
			x		= (index % ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_WIDTH + ENCOUNT_PATAPATA_FILL_WIDTH/2;	//	中心座標なので+WIDTH/2
			y		= (index / ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_HEIGHT + ENCOUNT_PATAPATA_FILL_HEIGHT/2;

			if( !ENCOUNT_PATAPATA_FILL_MoveParam1[ p_work->block_count ].wh ) {
				w	= 0;
				h	= ENCOUNT_PATAPATA_FILL_HEIGHT;
			}else{
				w	= ENCOUNT_PATAPATA_FILL_WIDTH;
				h	= 0;

			}
			// 発射
			ENC_BMP_FillSpreadStart(
					p_work->p_fill[ index ],
					x, y,
					p_work->one_fill_sync, p_work->p_bmp,
					w, h,
					ENCOUNT_PATAPATA_FILL_WIDTH, ENCOUNT_PATAPATA_FILL_HEIGHT,
					p_work->col );

			//	2つ目発射
			index	= ENCOUNT_PATAPATA_FILL_MoveParam_Reverse1( p_work->block_count );
			x		= (index % ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_WIDTH + ENCOUNT_PATAPATA_FILL_WIDTH/2;
			y		= (index / ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_HEIGHT + ENCOUNT_PATAPATA_FILL_HEIGHT/2;
			ENC_BMP_FillSpreadStart(
					p_work->p_fill[ index ],
					x, y,
					p_work->one_fill_sync, p_work->p_bmp,
					w, h,
					ENCOUNT_PATAPATA_FILL_WIDTH, ENCOUNT_PATAPATA_FILL_HEIGHT,
					p_work->col );

			p_work->block_count ++;
		}
	}


	// 動さ部
	for( i=p_work->block_end_count; i<p_work->block_count; i++ ){
		index	= ENCOUNT_PATAPATA_FILL_MoveParam_Order1( i );
		result = ENC_BMP_FillSpreadMain( p_work->p_fill[index] );
		index	= ENCOUNT_PATAPATA_FILL_MoveParam_Reverse1( i );
		result |= ENC_BMP_FillSpreadMain( p_work->p_fill[ index ] );
		if( result == TRUE ){
			p_work->block_end_count++;
		}
	}

	// 全動さ終了チェック
	if( (p_work->block_end_count >= ENCOUNT_PATAPATA_FILL_OBJNUM/2) &&
		(result == TRUE) ){
		p_work->init_flg = FALSE;
		return TRUE;
	}

	return FALSE;
}
BOOL ENC_BMP_PatapataFillMain2( ENC_BMP_PATAPATA_FILL *p_work )
{
	int x, y;
	int index;
	int i;
	BOOL result;

	static const u8 ENCOUNT_PATAPATA_FILL_MoveParam2[ ENCOUNT_PATAPATA_FILL_OBJNUM/2] = {	// 出てくる順番テーブル
	   	0,  1, 2,  3, 4, 5, 6, 7,
		16, 17, 18, 19, 20, 21, 22, 23,
		15,  14, 13, 12, 11, 10, 9, 8,
	};

	static const u8 ENCOUNT_PATAPATA_FILL_MoveParam2_r[ ENCOUNT_PATAPATA_FILL_OBJNUM/2] = {	// 出てくる順番テーブル
	   	31,  30,  29, 28,  27,  26, 25,  24,
		47, 46, 45, 44, 43, 42, 41, 40,
		32, 33,  34, 35, 36, 37, 38, 39,
	};

#define ENCOUNT_PATAPATA_FILL_MoveParam_Order2(x)	(ENCOUNT_PATAPATA_FILL_MoveParam2[ x ])
#define ENCOUNT_PATAPATA_FILL_MoveParam_Reverse2(x) (ENCOUNT_PATAPATA_FILL_MoveParam2_r[ x ])

	GF_ASSERT( p_work != NULL );

	//	未初期化時は終了
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	// 開始部
	if( p_work->block_count < ENCOUNT_PATAPATA_FILL_OBJNUM/2 ){
		p_work->wait --;
		if( p_work->wait <= 0 ){
			p_work->wait = p_work->one_start_sync;

			//	1つ目発射
			index	= ENCOUNT_PATAPATA_FILL_MoveParam_Order2( p_work->block_count );
			x		= (index % ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_WIDTH + ENCOUNT_PATAPATA_FILL_WIDTH/2;	//	中心座標なので+WIDTH/2
			y		= (index / ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_HEIGHT + ENCOUNT_PATAPATA_FILL_HEIGHT/2;
			// 発射
			ENC_BMP_FillSpreadStart(
					p_work->p_fill[ index ],
					x, y,
					p_work->one_fill_sync, p_work->p_bmp,
					0, ENCOUNT_PATAPATA_FILL_HEIGHT,
					ENCOUNT_PATAPATA_FILL_WIDTH, ENCOUNT_PATAPATA_FILL_HEIGHT,
					p_work->col );

			//	2つ目発射
			index	= ENCOUNT_PATAPATA_FILL_MoveParam_Reverse2( p_work->block_count );
			x		= (index % ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_WIDTH + ENCOUNT_PATAPATA_FILL_WIDTH/2;
			y		= (index / ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_HEIGHT + ENCOUNT_PATAPATA_FILL_HEIGHT/2;
			ENC_BMP_FillSpreadStart(
					p_work->p_fill[ index ],
					x, y,
					p_work->one_fill_sync, p_work->p_bmp,
					0, ENCOUNT_PATAPATA_FILL_HEIGHT,
					ENCOUNT_PATAPATA_FILL_WIDTH, ENCOUNT_PATAPATA_FILL_HEIGHT,
					p_work->col );

			p_work->block_count ++;
		}
	}


	// 動さ部
	for( i=p_work->block_end_count; i<p_work->block_count; i++ ){
		index	= ENCOUNT_PATAPATA_FILL_MoveParam_Order2( i );
		result = ENC_BMP_FillSpreadMain( p_work->p_fill[index] );
		index	= ENCOUNT_PATAPATA_FILL_MoveParam_Reverse2( i );
		result |= ENC_BMP_FillSpreadMain( p_work->p_fill[ index ] );
		if( result == TRUE ){
			p_work->block_end_count++;
		}
	}

	// 全動さ終了チェック
	if( (p_work->block_end_count >= ENCOUNT_PATAPATA_FILL_OBJNUM/2) &&
		(result == TRUE) ){
		p_work->init_flg = FALSE;
		return TRUE;
	}

	return FALSE;
}


BOOL ENC_BMP_PatapataFillMain3( ENC_BMP_PATAPATA_FILL *p_work )
{
	int x, y;
	int index;
	int i;
	BOOL result;

	static const u8 ENCOUNT_PATAPATA_FILL_MoveParam3[ ENCOUNT_PATAPATA_FILL_OBJNUM/2] = {	// 出てくる順番テーブル
	   	0,   2,  9, 16,  4, 11, 18, 25,
		32,  6, 13, 20, 27, 34, 41, 15,
		22, 29, 36, 43, 31, 38, 45, 47,
	};

	static const u8 ENCOUNT_PATAPATA_FILL_MoveParam3_r[ ENCOUNT_PATAPATA_FILL_OBJNUM/2] = {	// 出てくる順番テーブル
	   	1,   8,  3, 10, 17, 24,  5, 12,
		19, 26, 33, 40,  7, 14, 21, 28,
		35, 42, 23, 30, 37, 44, 39, 46,
	};

#define ENCOUNT_PATAPATA_FILL_MoveParam_Order3(x)	(ENCOUNT_PATAPATA_FILL_MoveParam3[ x ])
#define ENCOUNT_PATAPATA_FILL_MoveParam_Reverse3(x) (ENCOUNT_PATAPATA_FILL_MoveParam3_r[ x ])
#define ENCOUNT_PATAPATA_FILL_MoveParam_Order3_N(x)	(ENCOUNT_PATAPATA_FILL_OBJNUM - 1 - ENCOUNT_PATAPATA_FILL_MoveParam3[ x ])
#define ENCOUNT_PATAPATA_FILL_MoveParam_Reverse3_N(x) (ENCOUNT_PATAPATA_FILL_OBJNUM - 1 - ENCOUNT_PATAPATA_FILL_MoveParam3_r[ x ])

	GF_ASSERT( p_work != NULL );

	//	未初期化時は終了
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	// 開始部
	if( p_work->block_count < ENCOUNT_PATAPATA_FILL_OBJNUM/2 ){
		p_work->wait --;
		if( p_work->wait <= 0 ){
			p_work->wait = p_work->one_start_sync;

			//	1つ目発射

			if( p_work->b_morning ) {
				index	= ENCOUNT_PATAPATA_FILL_MoveParam_Order3( p_work->block_count );
			}else{
				// 夜なら逆再生
				index	= ENCOUNT_PATAPATA_FILL_MoveParam_Order3_N( p_work->block_count );
			}
			x		= (index % ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_WIDTH + ENCOUNT_PATAPATA_FILL_WIDTH/2;	//	中心座標なので+WIDTH/2
			y		= (index / ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_HEIGHT + ENCOUNT_PATAPATA_FILL_HEIGHT/2;
			// 発射
			ENC_BMP_FillSpreadStart(
					p_work->p_fill[ index ],
					x, y,
					p_work->one_fill_sync, p_work->p_bmp,
					0, 0,
					ENCOUNT_PATAPATA_FILL_WIDTH, ENCOUNT_PATAPATA_FILL_HEIGHT,
					p_work->col );

			//	2つ目発射
			if( p_work->b_morning ) {
				index	= ENCOUNT_PATAPATA_FILL_MoveParam_Reverse3( p_work->block_count );
			}else{
				index	= ENCOUNT_PATAPATA_FILL_MoveParam_Reverse3_N( p_work->block_count );
			}
			x		= (index % ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_WIDTH + ENCOUNT_PATAPATA_FILL_WIDTH/2;
			y		= (index / ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_HEIGHT + ENCOUNT_PATAPATA_FILL_HEIGHT/2;
			ENC_BMP_FillSpreadStart(
					p_work->p_fill[ index ],
					x, y,
					p_work->one_fill_sync, p_work->p_bmp,
					0, 0,
					ENCOUNT_PATAPATA_FILL_WIDTH, ENCOUNT_PATAPATA_FILL_HEIGHT,
					p_work->col );

			p_work->block_count ++;
		}
	}


	// 動さ部
	for( i=p_work->block_end_count; i<p_work->block_count; i++ ){
		int order_idx;
		int reverse_idx;

		if( p_work->b_morning ) {
			order_idx	= ENCOUNT_PATAPATA_FILL_MoveParam_Order3( i );
			reverse_idx	= ENCOUNT_PATAPATA_FILL_MoveParam_Reverse3( i );
		}else{
			order_idx	= ENCOUNT_PATAPATA_FILL_MoveParam_Order3_N( i );
			reverse_idx	= ENCOUNT_PATAPATA_FILL_MoveParam_Reverse3_N( i );
		}

		result = ENC_BMP_FillSpreadMain( p_work->p_fill[order_idx] );
		result |= ENC_BMP_FillSpreadMain( p_work->p_fill[reverse_idx] );
		if( result == TRUE ){
			p_work->block_end_count++;
		}
	}

	// 全動さ終了チェック
	if( (p_work->block_end_count >= ENCOUNT_PATAPATA_FILL_OBJNUM/2) &&
		(result == TRUE) ){
		p_work->init_flg = FALSE;
		return TRUE;
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *			【キャプチャシステム】
 *	@brief	キャプチャシステム作成
 *
 *	@param	u32 heapID						ヒープID
 *	@param	cp_param						キャプチャ引数構造体
 *
 *	@return	キャプチャシステムのワーク
 */
//-----------------------------------------------------------------------------
ENC_CAPTURE * ENC_CAPTURE_Create( u32 heapID, const ENC_CAPTURE_PARAM *cp_param )
{
	ENC_CAPTURE *	p_capture;
	p_capture = sys_AllocMemory(heapID, sizeof(ENC_CAPTURE));
	memset(p_capture, 0, sizeof(ENC_CAPTURE));

	//	VRAM状態を保存
#ifdef CAPTURE_SRC_VRAM_KEEP
	p_capture->p_vram_data	= sys_AllocMemory( heapID, VRAM_TBL[cp_param->use_vram].SIZE );
	MI_CpuCopy32( VRAM_TBL[cp_param->use_vram].LCDC_ADDR, p_capture->p_vram_data, VRAM_TBL[cp_param->use_vram].SIZE );
#endif // CAPTURE_SRC_VRAM_KEEP
	//	初期化
	p_capture->param	= *cp_param;
	p_capture->src_lcdc = GX_GetBankForLCDC();

	//	グラフィック設定
	GX_SetBankForLCDC( VRAM_TBL[cp_param->use_vram].BG_ADDR );
	MI_CpuClearFast( VRAM_TBL[cp_param->use_vram].LCDC_ADDR, VRAM_TBL[cp_param->use_vram].SIZE );

	return p_capture;
}

//----------------------------------------------------------------------------
/**
 *	@brief	キャプチャ実行
 *
 *	@param	ENC_CAPTURE *p_capture ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_CAPTURE_Execute( ENC_CAPTURE *p_capture )
{
	GX_SetCapture(
				p_capture->param.sz,			// キャプチャサイズ
				p_capture->param.mode,			// キャプチャモード
				p_capture->param.a,				// キャプチャブレンドA
				p_capture->param.b,				// キャプチャブレンドB
				p_capture->param.dest,			// 転送Vram
				p_capture->param.eva,			// ブレンド係数A
				p_capture->param.evb);			// ブレンド係数B
}

//----------------------------------------------------------------------------
/**
 *	@brief	キャプチャしたものを表示する
 *
 *	@param	ENC_CAPTURE *p_capture ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_CAPTURE_DrawCapture( ENC_CAPTURE *p_capture )
{
	GX_SetGraphicsMode( VRAM_TBL[p_capture->param.use_vram].DISPMODE, p_capture->param.bgMode, p_capture->param.bg0_2d3d);
}

//----------------------------------------------------------------------------
/**
 *	@brief	以前の画面に表示していたものを表示する
 *
 *	@param	ENC_CAPTURE *p_capture ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_CAPTURE_DrawReturn( ENC_CAPTURE *p_capture )
{
	GX_SetGraphicsMode( p_capture->param.dispMode, p_capture->param.bgMode, p_capture->param.bg0_2d3d );
}

//----------------------------------------------------------------------------
/**
 *	@brief	画面に表示している場所のアドレスを取得する
 *
 *	@param	ENC_CAPTURE *cp_capture ワーク
 *
 *	@return	アドレス
 */
//-----------------------------------------------------------------------------
void * ENC_CAPTURE_GetCaptureVramAddr( const ENC_CAPTURE *cp_capture )
{
	return VRAM_TBL[cp_capture->param.use_vram].LCDC_ADDR;
}

//----------------------------------------------------------------------------
/**
 *	@brief	キャプチャシステム解放
 *
 *	@param	ENC_CAPTURE *p_capture	ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_CAPTURE_Delete( ENC_CAPTURE *p_capture )
{
	//	LCDC復帰
	GX_SetBankForBG( p_capture->src_lcdc );
	MI_CpuClearFast( VRAM_TBL[p_capture->param.use_vram].LCDC_ADDR, VRAM_TBL[p_capture->param.use_vram].SIZE );

	ENC_CAPTURE_DrawReturn( p_capture );

	//	VRAM復帰処理
#ifdef CAPTURE_SRC_VRAM_KEEP
	MI_CpuCopy32( p_capture->p_vram_data, VRAM_TBL[p_capture->param.use_vram].LCDC_ADDR, VRAM_TBL[p_capture->param.use_vram].SIZE );
	sys_FreeMemoryEz( p_capture->p_vram_data );
#endif // CAPTURE_SRC_VRAM_KEEP

	//	ＢＧ面復帰
	GX_SetBankForBG( VRAM_TBL[p_capture->param.use_vram].BG_ADDR );
	GF_Disp_GX_VisibleControl( GX_PLANEMASK_BG1|GX_PLANEMASK_BG2|GX_PLANEMASK_BG3, VISIBLE_ON );

	//	システム解放
	sys_FreeMemoryEz( p_capture );
}


//=============================================================================
/**
 *	動作系
 */
//=============================================================================
//----------------------------------------------------------------------------
/**
 *	@brief	サインで幅内を揺れる処理初期化
 *
 *	@param	* p_work	ワーク
 *	@param	s_x			開始点
 *	@param	e_x			終了点
 *	@param	add			加算値（度数）
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_SinShakeMoveReq( ENC_SHAKEMOVE_WORK* p_work, s16 s_x, s16 e_x, s16 add )
{
	p_work->x	= s_x;
	p_work->s_x	= s_x;
	p_work->dist= e_x - s_x;
	p_work->add	= add;
	p_work->count	= 0;
}

//----------------------------------------------------------------------------
/**
 *	@brief	サインで幅内を揺れる処理メイン
 *
 *	@param	ENC_SHAKEMOVE_WORK* p_work	ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_SinShakeMoveMain( ENC_SHAKEMOVE_WORK* p_work )
{
	p_work->x	= p_work->s_x + ((FX_SinIdx( p_work->count ) * p_work->dist) >> FX32_SHIFT);
	p_work->count	+= FX_GET_ROTA_NUM(p_work->add);
}


//=============================================================================
/**
 *	曲同期

 *		前提
 *			この同期を使うには、BGMのローカル変数0番に拍ごとにカウントアップしていく
 *			値が入っていなければならない。
 *
 */
//=============================================================================
#define ENC_SYNCBGM_COUNT_VAR_NUM	(0)
//----------------------------------------------------------------------------
/**
 *	@brief	指定カウント内で、指定タイミングをとる初期化
 *			（例えば、5〜10カウントないで2ずつタイミングをとるといったことが可能）
 *
 *	@param	p_work		ワーク
 *	@param	var_end		カウント終了値（ENC_SYNCBGM_TIMING_BGMENDだとカウント終了まで）
 *	@param	timing		指定タイミング
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_SyncBgmTimingReq( ENC_SYNCBGM_TIMING_WORK* p_work, s16 var_end, fx32 timing )
{
	GF_ASSERT( p_work != NULL );
	p_work->var_start	= 0;
	p_work->var_end		= var_end;
	p_work->fx_timing	= timing;
	p_work->pre_var		= -1;
	p_work->init_flg	= 1;

	//	開始位置を取得
	Snd_ReadVariableByBgmNo( Snd_NowBgmNoGet(), ENC_SYNCBGM_COUNT_VAR_NUM, &p_work->var_start );
	//	初期チック
	p_work->tick_start	= Snd_PlayerGetTick(  Snd_GetPlayerNo(Snd_NowBgmNoGet()) );

}


//----------------------------------------------------------------------------
/**
 *	@brief	節ごとのタイミングを見る関数
 *			（もっとこれより良い方法があるはずだが暫定で）
 *
 *	@param	ENC_SYNCBGM_TIMING_WORK* p_work
 *
 *	@return	サーチ終了
 */
//-----------------------------------------------------------------------------
BOOL ENC_SyncBgmTimingSearch( ENC_SYNCBGM_TIMING_WORK* p_work )
{
	s16 var = 0;
	u32	tick;
	u16 now_bgm_no;

	//	初期化チェック
	if( p_work->init_flg == 1 ){
		now_bgm_no	= Snd_NowBgmNoGet();

		Snd_ReadVariableByBgmNo( now_bgm_no, ENC_SYNCBGM_COUNT_VAR_NUM, &var );
		tick= Snd_PlayerGetTick( Snd_GetPlayerNo( now_bgm_no ) );
		if( p_work->var_start + 1 == var ) {
			p_work->tick_add	= ((tick - p_work->tick_start) * p_work->fx_timing ) >> FX32_SHIFT;
			p_work->init_flg	= 2;	//	この関数の再読み込みを禁止
			return TRUE;
		}
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	指定カウント内で、指定タイミングをとるメイン
 *
 *	@param	ENC_SYNCBGM_TIMING_WORK* p_work	ワーク
 *	@param	*p_timing_flg					タイミング
 *
 *	@retval	TRUE	カウント終了
 *	@retval	FALSE	カウント続行中
 */
//-----------------------------------------------------------------------------
BOOL ENC_SyncBgmTimingMain( ENC_SYNCBGM_TIMING_WORK* p_work, BOOL *p_timing_flg )
{
	static const int COUNT_VAR_NUM	= 0;
	BOOL	result;
	s16		var	= -1;
	u32		tick;
	u16		now_bgm_no;
	*p_timing_flg	= FALSE;

	//	初期化チェック
	if( p_work->init_flg != 2 ){
		return TRUE;
	}

	//	カウント範囲内のみ
	now_bgm_no	= Snd_NowBgmNoGet();
	result	= Snd_ReadVariableByBgmNo( now_bgm_no, ENC_SYNCBGM_COUNT_VAR_NUM, &var );
	GF_ASSERT( result );
	if( p_work->var_start <= var ){

		//	動作
		tick	= Snd_PlayerGetTick( Snd_GetPlayerNo( now_bgm_no ) );

		//	チックが目標値になったらタイミングOK
		if( tick >= p_work->tick_start + p_work->tick_add ) {
			*p_timing_flg	= TRUE;
			p_work->tick_start	+= p_work->tick_add;
		}

		//	変数変更時にチックを見て、誤差を修正
		if( p_work->pre_var != var ) {
			p_work->tick_start	= tick;
		}

	}

	//	終了チェック
	if( p_work->var_end == ENC_SYNCBGM_TIMING_BGMEND ) {
		if( var == p_work->pre_var ){
			p_work->init_flg = 0;
			return TRUE;
		}
	}else{
		if( var >= p_work->var_end ){
			p_work->init_flg = 0;
			return TRUE;
		}
	}
	p_work->pre_var		= var;

	return FALSE;
}


//----------------------------------------------------------------------------
/**
 *		【曲同期、BMPランダムぬりつぶし】
 *	@brief	BMPランダム塗りつぶしワーク作成
 *
 *	@param	heapID	ヒープID
 *
 *	@return	ワーク
 */
//-----------------------------------------------------------------------------
ENC_BMP_SYNCBGM_RNDFILL* ENC_BMP_SYNCBGM_RndFillAlloc( u32 heapID )
{
	ENC_BMP_SYNCBGM_RNDFILL* p_work;
	int i;

	p_work = sys_AllocMemory( heapID, sizeof(ENC_BMP_SYNCBGM_RNDFILL) );
	memset( p_work, 0, sizeof(ENC_BMP_SYNCBGM_RNDFILL) );

	return p_work;
}

//----------------------------------------------------------------------------
/**
 *		【曲同期、BMPランダムぬりつぶし】
 *	@brief	BMPランダム塗りつぶしワーク破棄
 *
 *	@param	p_work	ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_BMP_SYNCBGM_RndFillDelete( ENC_BMP_SYNCBGM_RNDFILL* p_work )
{
	sys_FreeMemoryEz( p_work );
}

//----------------------------------------------------------------------------
/**
 *		【曲同期、BMPランダムぬりつぶし】
 *	@brief	BMPランダム塗りつぶしエフェクト開始
 *
 *	@param	p_work	ワーク
 *	@param	p_bmp	ビットマップ
 *	@param	col		カラー
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_BMP_SYNCBGM_RndFillStart( ENC_BMP_SYNCBGM_RNDFILL* p_work, s16 var_end, s16 timing, GF_BGL_BMPWIN* p_bmp, u8 col )
{
	p_work->p_bmp		= p_bmp;
	p_work->col			= col;
	p_work->block_count = 0;
	p_work->init_flg	= 1;

	ENC_InitNonRepeatRnd( &p_work->rnd, ENCOUNT_BLOCK_RND_OBJNUM );
	ENC_SyncBgmTimingReq( &p_work->timing, var_end, timing );

	p_work->start_num	= (ENCOUNT_BLOCK_RND_OBJNUM / (FX_Div(FX32_CONST(var_end - p_work->timing.var_start), timing) >> FX32_SHIFT) );
}

//----------------------------------------------------------------------------
/**
 *		【曲同期、BMPランダムぬりつぶし】
 *	@brief	BMPランダム塗りつぶしメイン処理
 *
 *	@param	p_work	ワーク
 *
 *	@retval	TRUE	終了
 *	@retval FALSE	途中
 */
//-----------------------------------------------------------------------------
BOOL ENC_BMP_SYNCBGM_RndFillMain( ENC_BMP_SYNCBGM_RNDFILL* p_work )
{
	int i;
	u16 rnd;
	s16 left, top, right, bottom;
	s16 x, y;
	BOOL result;
	BOOL timing_flg	= FALSE;

	GF_ASSERT( p_work != NULL );

	//	初期化チェック
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	ENC_SyncBgmTimingSearch( &p_work->timing );
	result	= ENC_SyncBgmTimingMain( &p_work->timing, &timing_flg );
	NAGIHASHI_PRINT("タイミング：%d\n", timing_flg);

	// 次々とFillしていく
	if( timing_flg ){
		for( i = 0; i < p_work->start_num; i++ ) {
			if( p_work->block_count < ENCOUNT_BLOCK_RND_OBJNUM ){
				//	発射
				rnd	= ENC_GetNonRepeatRnd( &p_work->rnd );
				//	ランダムで座標を求める
				x		= (rnd % ENCOUNT_BLOCK_RND_X_NUM) * ENCOUNT_BLOCK_RND_WIDTH;
				y		= (rnd / ENCOUNT_BLOCK_RND_X_NUM) * ENCOUNT_BLOCK_RND_HEIGHT;
				//	中心座標を矩形座標に直す
				left	= x;
				top		= y;;
				right	= x + (ENCOUNT_BLOCK_RND_WIDTH/*/2*/);
				bottom	= y + (ENCOUNT_BLOCK_RND_HEIGHT/*/2*/);
				//	Fill
				ENC_BMP_Fill( p_work->p_bmp, top, bottom, left, right, p_work->col );
				p_work->block_count ++;
			}
		}
	}
	//	終了チェック
	if( p_work->block_count >= ENCOUNT_BLOCK_RND_OBJNUM ) {
		p_work->init_flg = FALSE;
		return TRUE;
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *		【曲同期、BMPパタパタぬりつぶし】
 *	@brief	BMPランダム塗りつぶしワーク作成
 *
 *	@param	heapID	ヒープID
 *
 *	@return	ワーク
 */
//-----------------------------------------------------------------------------
ENC_BMP_SYNCBGM_PATAFILL* ENC_BMP_SYNCBGM_PataFillAlloc( u32 heapID )
{
	ENC_BMP_SYNCBGM_PATAFILL* p_work;
	int i;

	p_work = sys_AllocMemory( heapID, sizeof(ENC_BMP_SYNCBGM_PATAFILL) );
	memset( p_work, 0, sizeof(ENC_BMP_SYNCBGM_PATAFILL) );

	for( i = 0; i <ENCOUNT_PATAPATA_FILL_OBJNUM; i++ ) {
		p_work->p_fill[i]	= ENC_BMP_FillSpreadAlloc( heapID );
	}


	return p_work;
}

//----------------------------------------------------------------------------
/**
 *		【曲同期、BMPパタパタぬりつぶし】
 *	@brief	BMPランダム塗りつぶしワーク破棄
 *
 *	@param	p_work	ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_BMP_SYNCBGM_PataFillDelete( ENC_BMP_SYNCBGM_PATAFILL* p_work )
{
	int i;
	GF_ASSERT( p_work != NULL );

	for( i = 0; i <ENCOUNT_PATAPATA_FILL_OBJNUM; i++ ) {
		ENC_BMP_FillSpreadDelete( p_work->p_fill[i] );
	}
	sys_FreeMemoryEz( p_work );
}

//----------------------------------------------------------------------------
/**
 *		【曲同期、BMPパタパタぬりつぶし】
 *	@brief	BMPランダム塗りつぶしエフェクト開始
 *
 *	@param	p_work	ワーク
 *	@param	p_bmp	ビットマップ
 *	@param	col		カラー
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
void ENC_BMP_SYNCBGM_PataFillStart( ENC_BMP_SYNCBGM_PATAFILL* p_work, s16 var_end, fx32 timing, GF_BGL_BMPWIN* p_bmp, u8 col )
{
	p_work->p_bmp		= p_bmp;
	p_work->col			= col;
	p_work->block_count = 0;
	p_work->init_flg	= 1;
	p_work->block_end_count	= 0;
	p_work->one_fill_sync	= 5;	//	とりあえず

	ENC_SyncBgmTimingReq( &p_work->timing, var_end, timing );
	p_work->move_obj_num= (ENCOUNT_PATAPATA_FILL_OBJNUM / (FX_Div(FX32_CONST(var_end - p_work->timing.var_start), timing) >> FX32_SHIFT) ) ;
	NAGIHASHI_PRINT( "PATA_OBJ_NUM:%d E%d S%d %d \n", p_work->move_obj_num, var_end, p_work->timing.var_start, 0 );

	p_work->move_obj_num	= p_work->move_obj_num == 0 ? 1: p_work->move_obj_num;
}

//----------------------------------------------------------------------------
/**
 *		【曲同期、BMPパタパタぬりつぶし】
 *	@brief	BMPランダム塗りつぶしメイン処理
 *
 *	@param	p_work	ワーク
 *
 *	@retval	TRUE	終了
 *	@retval FALSE	途中
 */
//-----------------------------------------------------------------------------
BOOL ENC_BMP_SYNCBGM_PataFillMain( ENC_BMP_SYNCBGM_PATAFILL* p_work )
{
	int x, y;
	int index;
	int i;
	BOOL result;
	BOOL timing_flg	= FALSE;

	GF_ASSERT( p_work != NULL );

	//	未初期化時は終了
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	//	曲の同期を取得
	ENC_SyncBgmTimingSearch( &p_work->timing );
	ENC_SyncBgmTimingMain( &p_work->timing, &timing_flg );
	NAGIHASHI_PRINT("タイミング：%d\n", timing_flg);

	//	開始
	if( timing_flg ){
		for( i = 0; i < p_work->move_obj_num; i++ ) {
			// 開始部
			if( p_work->block_count < ENCOUNT_PATAPATA_FILL_OBJNUM ){

				index	= ENCOUNT_SYNCBGM_PATAFILL_MoveParam[ p_work->block_count ];
				x		= (index % ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_WIDTH + ENCOUNT_PATAPATA_FILL_WIDTH/2;	//	中心座標なので+WIDTH/2
				y		= (index / ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_HEIGHT + ENCOUNT_PATAPATA_FILL_HEIGHT/2;
				// 発射
				ENC_BMP_FillSpreadStart(
						p_work->p_fill[ index ],
						x, y,
						p_work->one_fill_sync, p_work->p_bmp,
						0, ENCOUNT_PATAPATA_FILL_HEIGHT,
						ENCOUNT_PATAPATA_FILL_WIDTH,
						ENCOUNT_PATAPATA_FILL_HEIGHT,
						p_work->col );
				p_work->block_count ++;
			}
		}
	}


	// 動さ
	for( i = p_work->block_end_count; i < p_work->block_count; i++ ){
		index	= ENCOUNT_SYNCBGM_PATAFILL_MoveParam[ i ];
		result = ENC_BMP_FillSpreadMain( p_work->p_fill[index] );
		if( result == TRUE ){
			p_work->block_end_count++;
		}
	}

	// 全動さ終了チェック
	if( (p_work->block_end_count >= ENCOUNT_PATAPATA_FILL_OBJNUM) &&
		(result == TRUE) ){
		p_work->init_flg = FALSE;
		return TRUE;
	}

	return FALSE;
}

BOOL ENC_BMP_SYNCBGM_PataFillMain1( ENC_BMP_SYNCBGM_PATAFILL* p_work )
{
	static const struct {
		u8 idx;
		u8 wh;	//	縦なら1横なら0
	}ENCOUNT_PATAPATA_FILL_MoveParam1[ ENCOUNT_PATAPATA_FILL_OBJNUM] = {	// 出てくる順番テーブル
		{0,0},	{47,0}, {1,0}, {46,0}, {2,0}, {45,0}, {3,0}, {44,0}, {4,0}, {43,0}, {5,0}, {42,0}, {6,0}, {41,0}, {7,1},{40,1},
		{15,1},{32,1}, {23,1}, {24,1},{31,1},{16,1}, {39,0},{8,0}, {38,0},{9,0}, {37,0},{10,0}, {36,0}, {11,0},{35,0},{12,0},
		{34,0},{13,0}, {33,1},{14,1}, {25,1}, {22,1},{17,0}, {30,0},{18,0}, {29,0},{19,0}, {28,0},{20,0}, {27,0},{21,0},{26,0},
	};

	int x, y;
	int w, h;
	u8 index;
	int count;
	int i;
	BOOL result;
	BOOL timing_flg	= FALSE;

	GF_ASSERT( p_work != NULL );

	//	未初期化時は終了
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	//	曲の同期を取得
	ENC_SyncBgmTimingSearch( &p_work->timing );
	ENC_SyncBgmTimingMain( &p_work->timing, &timing_flg );
	NAGIHASHI_PRINT("タイミング：%d", timing_flg);

	//	開始
	if( timing_flg ){
		for( i = 0; i < p_work->move_obj_num; i++ ) {
			// 開始部
			if( p_work->block_count < ENCOUNT_PATAPATA_FILL_OBJNUM ){
				index	= ENCOUNT_PATAPATA_FILL_MoveParam1[p_work->block_count].idx;

				x		= (index % ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_WIDTH + ENCOUNT_PATAPATA_FILL_WIDTH/2;	//	中心座標なので+WIDTH/2
				y		= (index / ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_HEIGHT + ENCOUNT_PATAPATA_FILL_HEIGHT/2;
				if( !ENCOUNT_PATAPATA_FILL_MoveParam1[ p_work->block_count].wh ) {
					w	= 0;
					h	= ENCOUNT_PATAPATA_FILL_HEIGHT;
				}else{
					w	= ENCOUNT_PATAPATA_FILL_WIDTH;
					h	= 0;
				}
				// 発射
				ENC_BMP_FillSpreadStart(
						p_work->p_fill[ index ],
						x, y,
						p_work->one_fill_sync, p_work->p_bmp,
						w, h,
						ENCOUNT_PATAPATA_FILL_WIDTH,
						ENCOUNT_PATAPATA_FILL_HEIGHT,
						p_work->col );
				p_work->block_count ++;
			}
		}
		NAGIHASHI_PRINT("Start %d \n", i);
	}else{
		NAGIHASHI_PRINT("Stop\n");
	}


	// 動さ
	for( i = p_work->block_end_count; i < p_work->block_count; i++ ){
		index	= ENCOUNT_PATAPATA_FILL_MoveParam1[i].idx;
		result = ENC_BMP_FillSpreadMain( p_work->p_fill[index] );
		if( result == TRUE ){
			p_work->block_end_count++;
		}
	}

	// 全動さ終了チェック
	if( (p_work->block_end_count >= ENCOUNT_PATAPATA_FILL_OBJNUM) &&
		(result == TRUE) ){
		p_work->init_flg = FALSE;
		return TRUE;
	}

	return FALSE;
}

BOOL ENC_BMP_SYNCBGM_PataFillMain2( ENC_BMP_SYNCBGM_PATAFILL* p_work )
{
	int x, y;
	int index;
	int i;
	BOOL result;
	BOOL timing_flg	= FALSE;

	GF_ASSERT( p_work != NULL );

	//	未初期化時は終了
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	//	曲の同期を取得
	ENC_SyncBgmTimingSearch( &p_work->timing );
	ENC_SyncBgmTimingMain( &p_work->timing, &timing_flg );
	NAGIHASHI_PRINT("タイミング：%d\n", timing_flg);

	//	開始
	if( timing_flg ){
		for( i = 0; i < p_work->move_obj_num; i++ ) {
			// 開始部
			if( p_work->block_count < ENCOUNT_PATAPATA_FILL_OBJNUM ){

				index	= ENCOUNT_SYNCBGM_PATAFILL_MoveParam[ p_work->block_count ];
				x		= (index % ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_WIDTH + ENCOUNT_PATAPATA_FILL_WIDTH/2;	//	中心座標なので+WIDTH/2
				y		= (index / ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_HEIGHT + ENCOUNT_PATAPATA_FILL_HEIGHT/2;
				// 発射
				ENC_BMP_FillSpreadStart(
						p_work->p_fill[ index ],
						x, y,
						p_work->one_fill_sync, p_work->p_bmp,
						0, ENCOUNT_PATAPATA_FILL_HEIGHT,
						ENCOUNT_PATAPATA_FILL_WIDTH,
						ENCOUNT_PATAPATA_FILL_HEIGHT,
						p_work->col );
				p_work->block_count ++;
			}
		}
	}


	// 動さ
	for( i = p_work->block_end_count; i < p_work->block_count; i++ ){
		index	= ENCOUNT_SYNCBGM_PATAFILL_MoveParam[ i ];
		result = ENC_BMP_FillSpreadMain( p_work->p_fill[index] );
		if( result == TRUE ){
			p_work->block_end_count++;
		}
	}

	// 全動さ終了チェック
	if( (p_work->block_end_count >= ENCOUNT_PATAPATA_FILL_OBJNUM) &&
		(result == TRUE) ){
		p_work->init_flg = FALSE;
		return TRUE;
	}

	return FALSE;
}

BOOL ENC_BMP_SYNCBGM_PataFillMain3( ENC_BMP_SYNCBGM_PATAFILL* p_work )
{
static const u8 ENCOUNT_PATAPATA_FILL_MoveParam3[ ENCOUNT_PATAPATA_FILL_OBJNUM] = {	// 出てくる順番テーブル
	   	0, 1,  2, 8, 9, 3,16,10,  4,17, 11,24, 18,5, 25,12,
		32,19,  6,26, 13,33, 20,40, 27,7, 34,14, 41,21, 15,28,
		22, 35,29,42, 36,23, 43,30, 31,37, 38,44, 45,39, 47,46,
	};

	int x, y;
	int index;
	int i;
	BOOL result;
	BOOL timing_flg	= FALSE;

	GF_ASSERT( p_work != NULL );

	//	未初期化時は終了
	if( p_work->init_flg == 0 ){
		return TRUE;
	}

	//	曲の同期を取得
	ENC_SyncBgmTimingSearch( &p_work->timing );
	ENC_SyncBgmTimingMain( &p_work->timing, &timing_flg );
	NAGIHASHI_PRINT("タイミング：%d\n", timing_flg);

	//	開始
	if( timing_flg ){
		for( i = 0; i < p_work->move_obj_num; i++ ) {
			// 開始部
			if( p_work->block_count < ENCOUNT_PATAPATA_FILL_OBJNUM ){

				index	=  ENCOUNT_PATAPATA_FILL_MoveParam3[ p_work->block_count ];
				x		= (index % ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_WIDTH + ENCOUNT_PATAPATA_FILL_WIDTH/2;	//	中心座標なので+WIDTH/2
				y		= (index / ENCOUNT_PATAPATA_FILL_X_NUM) * ENCOUNT_PATAPATA_FILL_HEIGHT + ENCOUNT_PATAPATA_FILL_HEIGHT/2;
				// 発射
				ENC_BMP_FillSpreadStart(
						p_work->p_fill[ index ],
						x, y,
						p_work->one_fill_sync, p_work->p_bmp,
						0, ENCOUNT_PATAPATA_FILL_HEIGHT,
						ENCOUNT_PATAPATA_FILL_WIDTH,
						ENCOUNT_PATAPATA_FILL_HEIGHT,
						p_work->col );
				p_work->block_count ++;
			}
		}
	}


	// 動さ
	for( i = p_work->block_end_count; i < p_work->block_count; i++ ){
		index	=  ENCOUNT_PATAPATA_FILL_MoveParam3[ i ];
		result = ENC_BMP_FillSpreadMain( p_work->p_fill[index] );
		if( result == TRUE ){
			p_work->block_end_count++;
		}
	}

	// 全動さ終了チェック
	if( (p_work->block_end_count >= ENCOUNT_PATAPATA_FILL_OBJNUM) &&
		(result == TRUE) ){
		p_work->init_flg = FALSE;
		return TRUE;
	}

	return FALSE;
}



//-----------------------------------------------------------------------------
// 実体
//-----------------------------------------------------------------------------

//-------------------------------------
///	シーケンスシステム
//=====================================
typedef BOOL (*ENC_SUBSEQ_FUNTION)( void *, u32 * );
typedef struct {
	ENC_SUBSEQ_FUNTION	function;
	u32					seq;
}ENC_SUBSEQ;

static void ENC_SUBSEQ_Init( ENC_SUBSEQ *p_wk, ENC_SUBSEQ_FUNTION function );
static BOOL ENC_SUBSEQ_Main( ENC_SUBSEQ *p_wk, void *p_data );

//-------------------------------------
//	モンスターボールの簡易読み込み関係
//=====================================
typedef enum {
	ENC_CLACT_BALL_OLD,
	ENC_CLACT_BALL_NEW,
} ENC_CLACT_BALL_TYPE;
static void ENC_CLACT_BALL_Load( ARCHANDLE* p_handle, CLACT_WORK_PTR *pp_clact, ENC_CLACT_SYS* p_clsys, ENC_CLACT_RES_WORK* p_clres, ENC_CLACT_BALL_TYPE type );

//-------------------------------------
///		旧金銀のエンカウント再現
//=====================================
#define ENCOUNT_OLD_WIPEOUT_SYNC		(28)	// ワイプアウトシンク数
#define ENCOUNT_OLD_SUBSEQ_NUM			(3)	// サブシーケンスの数
#define ENCOUNT_OLD_CELL_NUM			(2)		// セルの数
#define ENCOUNT_OLD_CELL_RES_NUM		(1)		// リソースの数
#define ENCOUNT_OLD_RANDFILL_START_SYNC	(0)		// ブロックが埋め尽くされるかうんと
#define ENCOUNT_OLD_RANDFILL_FILLCOLOR	(15)	// ブロックが塗りつぶされる色

// #define ENCOUNT_OLD_BGMSYNC_RNDFILL	//	RNDFILLをBGMSYNCさせるか

typedef struct{
	GF_BGL_BMPWIN			*p_bmp;			// BMP本体
#ifdef ENCOUNT_OLD_BGMSYNC_RNDFILL
	ENC_BMP_SYNCBGM_RNDFILL	*p_fill;
#else
	ENC_BMP_RND_FILL		*p_fill;		// ランダムぬりつぶし
#endif  //ENCOUNT_OLD_BGMSYNC_RNDFILL
	FIELD_HBLANK_SYS		*p_hblank;		// HBlankデータ
	u32						subseq_index;	// 分岐NO（0〜2）
	ENC_CLACT_SYS			clact_sys;		// CLACTシステム
	ENC_CLACT_RES_WORK		clact_res;		// CLACTリソースワーク
	CLACT_WORK_PTR			clwk_ball;		// CLWKボールの絵
	ENC_SUBSEQ				subseq[ENCOUNT_OLD_SUBSEQ_NUM];		// サブシーケンスの数
} ENCOUNT_TEST_OLD;
static BOOL ENCOLD_SUBSEQ_RndFill( void *p_data, u32 *p_seq );
static BOOL ENCOLD_SUBSEQ_SpreadRect( void *p_data, u32 *p_seq );
static BOOL ENCOLD_SUBSEQ_ClockFill( void *p_data, u32 *p_seq );

//--------------------------------------------------------------
///	パタパタ エンカウントエフェクト
//==============================================================
typedef struct{
	GF_BGL_BMPWIN			*p_bmp;			// BMP本体
#ifdef ENCOUNT_PATAPATA_BGMSYNC
	ENC_BMP_SYNCBGM_PATAFILL	*p_pata;
#else
	ENC_BMP_PATAPATA_FILL	*p_pata;		// パタパタ塗りつぶし
#endif	//ENCOUNT_PATAPATA_BGMSYNC

} ENCOUNT_TEST_PATAPATA;
// スピード
#define ENCOUNT_PATAPATA_START_SYNC	(0)		//一辺の塗りつぶし矩形開始シンク
#define ENCOUNT_PATAPATA_FILL_SYNC	(4)		//一辺の塗りつぶし処理シンク

//-----------------------------------------------------------------------------

#define ENCOUNT_PATAPATA_BLOCK_FILLCOLOR ( 15 )	// 塗りつぶし

//--------------------------------------------------------------
///	BG転送用のワーク
//==============================================================
typedef struct {
	// [IN]
	ENCOUNT_EFFECT_WORK* eew;
	void* charBuff1;
	void* charBuff2;
	NNSG2dCharacterData* charData1;
	NNSG2dCharacterData* charData2;
	// [PRIVATE]
	TCB_PTR tcb;		// 親TCB
	TCB_PTR tcbVIntr;	// 転送用TCB(子)
	u16 seq;
	u16 vseq;
} WATER_LOAD_WORK;

//-------------------------------------
///		水場のエンカウント
//=====================================
typedef struct{
	ENCOUNT_LASTER_SCROLL	laster;
	ENC_ADDMOVE_WORK_FX		move_y1;		// 泡Y座標
	ENC_ADDMOVE_WORK_FX		move_y2;
	ENC_SHAKEMOVE_WORK		shake_x;
	u32						wait;			// lasterかける時間
	u8						bg1_start;		// 泡一枚目動作開始
	u8						bg2_start;		// 泡二枚目動作開始
	u8						bg1_end;		// 泡１動作終了
	u8						bg2_end;		// 泡２動作終了
	WATER_LOAD_WORK			wkLoad;
} ENCOUNT_TEST_WATER;
#define ENCOUNT_TESTWATER_LASTER_SYNC		(10)//(20)					// ラスタにかかるシンク
#define ENCOUNT_TESTWATER_LASTER_SIN_ADDR	((0xffff/192)*10)		// ラスター角度スピード
#define ENCOUNT_TESTWATER_LASTER_SIN_R		(FX32_CONST(3))			// 半径
#define ENCOUNT_TESTWATER_LASTER_SPD		(400)					// ラスタースピード
#define ENCOUNT_TESTWATER_LASTER_TASK_PRI	(TCB_TSK_PRI - 1)		// タスク優先度

#define ENCOUNT_TESTWATER_BG_START_ADD1		(FX32_CONST(0))			//初速1
#define ENCOUNT_TESTWATER_BG_START_ADD2		(FX32_CONST(8))			//初速2
#define ENCOUNT_TESTWATER_BG_START_Y		(FX32_CONST(0))			//開始座標Y
#define ENCOUNT_TESTWATER_BG_END_Y			(FX32_CONST(320))		//終了座標X
#define ENCOUNT_TESTWATER_BG1_SYNC			(18)					//BG移動シンク
#define ENCOUNT_TESTWATER_BG2_SYNC			(30)					//BG移動シンク
#define ENCOUNT_TESTWATER_BG_X				(0)						//泡の座標X

///追加ここまで------------

//-----------------------------------------------------------------------------
/**
 *	以下、名木橋追加分
 */
//-----------------------------------------------------------------------------

//=============================================================================
/**
 *	シーケンスシステム
 */
//=============================================================================
//----------------------------------------------------------------------------
/**
 *	@brief	シーケンスを初期化
 *
 *	@param	ENC_SUBSEQ *p_wk	シーケンスワーク
 *	@param	function			実行ジーケンス関数
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void ENC_SUBSEQ_Init( ENC_SUBSEQ *p_wk, ENC_SUBSEQ_FUNTION function )
{
	p_wk->function	= function;
	p_wk->seq		= 0;
}

//----------------------------------------------------------------------------
/**
 *	@brief	シーケンス実行
 *
 *	@param	ENC_SUBSEQ *p_wk	シーケンスワーク
 *	@param	*p_data				実行関数に渡すデータ
 *
 *	@return
 */
//-----------------------------------------------------------------------------
static BOOL ENC_SUBSEQ_Main( ENC_SUBSEQ *p_wk, void *p_data )
{
	return p_wk->function( p_data, &p_wk->seq );
}

//----------------------------------------------------------------------------
/**
 *	@brief	昔の金銀エンカウントの再現エフェクト
 *
 *	@param	tcb
 *	@param	work
 *
 *	@return
 */
//-----------------------------------------------------------------------------
void EncountEffect_Test_Old(TCB_PTR tcb, void* work)
{
	//	シーケンス
	enum _SEQ {
		SEQ_INIT,
		SEQ_FLASH_INIT,
		SEQ_FLASH_MAIN,
		SEQ_SUBSEQ_RAND,
		SEQ_SUBSEQ_MAIN,
		SEQ_EXIT,
	};

	ENCOUNT_EFFECT_WORK		*eew	= work;
	ENCOUNT_TEST_OLD		*tw		= eew->work;
	BOOL					result;
	int						i;

	switch( eew->seq ){
	//	初期化
	case SEQ_INIT:
		eew->work = sys_AllocMemory( HEAPID_FIELD, sizeof(ENCOUNT_TEST_OLD) );
		memset( eew->work, 0, sizeof(ENCOUNT_TEST_OLD) );
		tw	= eew->work;

		// ビットマップウィンドウ作成
		tw->p_bmp = GF_BGL_BmpWinAllocGet( HEAPID_FIELD, 1 );
		GF_BGL_BmpWinAdd( eew->fsw->bgl, tw->p_bmp, GF_BGL_FRAME3_M, 0, 0, 32, 32, 0, 0 );

		// カラーパレット転送
		{
			GXRgb color = 0;
			GF_BGL_PaletteSet( GF_BGL_FRAME3_M, &color, sizeof(GXRgb), 2*0xF );
		}
		GF_BGL_BmpWinDataFill( tw->p_bmp, 0 );
		GF_BGL_BmpWinOnVReq( tw->p_bmp );

		// セルアクターセット作成
		ENC_CLACT_Init( &tw->clact_sys, ENCOUNT_OLD_CELL_NUM, ENCOUNT_OLD_CELL_RES_NUM );
		ENC_CLACT_BALL_Load( eew->p_handle, &tw->clwk_ball, &tw->clact_sys, &tw->clact_res, ENC_CLACT_BALL_OLD );
		GF_Disp_GX_VisibleControl( GX_PLANEMASK_OBJ, VISIBLE_ON );

		//	サブシーケンス初期化
		tw->p_hblank	=  eew->fsw->fldmap->hblanksys;
		ENC_SUBSEQ_Init( &tw->subseq[0], ENCOLD_SUBSEQ_RndFill );
		ENC_SUBSEQ_Init( &tw->subseq[1], ENCOLD_SUBSEQ_SpreadRect );
		ENC_SUBSEQ_Init( &tw->subseq[2], ENCOLD_SUBSEQ_ClockFill );

		eew->seq	= SEQ_FLASH_INIT;
		break;

	//	フラッシュ初期化
	case SEQ_FLASH_INIT:
		EncountFlashTask(MASK_MAIN_DISPLAY, -16, -16,  &eew->wait, 2);
		eew->seq	= SEQ_FLASH_MAIN;
		break;

	//	フラッシュ処理
	case SEQ_FLASH_MAIN:
		if( eew->wait ){
			eew->seq	= SEQ_SUBSEQ_RAND;
		}
		break;

	//	サブシーケンス初期化
	case SEQ_SUBSEQ_RAND:
		tw->subseq_index	= 0;//gf_rand() % ENCOUNT_OLD_SUBSEQ_NUM;
		eew->seq	= SEQ_SUBSEQ_MAIN;
		break;

		//	サブシーケンス処理
	case SEQ_SUBSEQ_MAIN:
		if( ENC_SUBSEQ_Main( &tw->subseq[tw->subseq_index], tw ) ){
			eew->seq	= SEQ_EXIT;
		}
		break;

	//	終了処理
	case SEQ_EXIT:
		WIPE_SetBrightnessFadeOut( WIPE_FADE_BLACK );

		if(eew->end != NULL){
			*(eew->end) = TRUE;		// タスク終了を報告
		}

		// ビットマップ破棄
		GF_BGL_BmpWinOff( tw->p_bmp );
		GF_BGL_BmpWinDel( tw->p_bmp );
		GF_BGL_BmpWinFree( tw->p_bmp, 1 );

		//	CLACT
		CLACT_Delete( tw->clwk_ball );
		ENC_CLACT_ResDeleteEasy( &tw->clact_sys, &tw->clact_res );
		ENC_CLACT_Delete( &tw->clact_sys );

		ENC_End( eew, tcb );
		return ;
	}


	if( eew->seq != SEQ_EXIT ){
		CLACT_Draw( tw->clact_sys.cas );
	}
}


//----------------------------------------------------------------------------
/**
 *	@brief	サブシーケンス：ランダムにドットをうって画面を埋める処理
 *
 *	@param	void *p_data	貰ったデータ
 *	@param	*p_seq			シーケンス
 *
 *	@retval	TRUE	終了
 *	@retval	FALSE	継続
 */
//-----------------------------------------------------------------------------
static BOOL ENCOLD_SUBSEQ_RndFill( void *p_data, u32 *p_seq )
{
	enum  {
		SEQ_INIT,
		SEQ_MAIN,
		SEQ_EXIT,
	};
	ENCOUNT_TEST_OLD	*p_wk	= p_data;
	BOOL				result;

	switch( *p_seq ) {
	case SEQ_INIT:
#ifdef ENCOUNT_OLD_BGMSYNC_RNDFILL
		p_wk->p_fill = ENC_BMP_SYNCBGM_RndFillAlloc( HEAPID_FIELD );
		ENC_BMP_SYNCBGM_RndFillStart( p_wk->p_fill,8, FX32_CONST(6)/48, p_wk->p_bmp, ENCOUNT_OLD_RANDFILL_FILLCOLOR );
#else
		p_wk->p_fill = ENC_BMP_RndFillAlloc( HEAPID_FIELD );
		ENC_BMP_RndFillStart( p_wk->p_fill,
				ENCOUNT_OLD_RANDFILL_START_SYNC,
				p_wk->p_bmp, ENCOUNT_OLD_RANDFILL_FILLCOLOR );
#endif // ENCOUNT_OLD_BGMSYNC_RNDFILL
		*p_seq	= SEQ_MAIN;
		break;

	case SEQ_MAIN:
#ifdef ENCOUNT_OLD_BGMSYNC_RNDFILL
		result	= ENC_BMP_SYNCBGM_RndFillMain( p_wk->p_fill );
#else
		result	= ENC_BMP_RndFillMain( p_wk->p_fill );
#endif // ENCOUNT_OLD_BGMSYNC_RNDFILL
		GF_BGL_BmpWinOnVReq( p_wk->p_bmp );
		if( result ) {
			*p_seq	= SEQ_EXIT;
		}
		break;

	case SEQ_EXIT:
#ifdef ENCOUNT_OLD_BGMSYNC_RNDFILL
		ENC_BMP_SYNCBGM_RndFillDelete( p_wk->p_fill );
#else
		ENC_BMP_RndFillDelete( p_wk->p_fill );
#endif // ENCOUNT_OLD_BGMSYNC_RNDFILL
		*p_seq	= 0;
		return TRUE;

	default :
		GF_ASSERT( 0 );
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	サブシーケンス：矩形が広がる処理
 *
 *	@param	void *p_data	貰ったデータ
 *	@param	*p_seq			シーケンス
 *
 *	@retval	TRUE	終了
 *	@retval	FALSE	継続
 */
//-----------------------------------------------------------------------------
static BOOL ENCOLD_SUBSEQ_SpreadRect( void *p_data, u32 *p_seq )
{
	enum  {
		SEQ_INIT,
		SEQ_MAIN,
		SEQ_EXIT,
	};
	ENCOUNT_TEST_OLD	*p_wk	= p_data;

	switch( *p_seq ) {
	case SEQ_INIT:
		FLDHBLANK_SYS_Stop( p_wk->p_hblank );
		WIPE_SYS_Start( WIPE_PATTERN_M, WIPE_TYPE_ROUNDOUT, WIPE_TYPE_ROUNDOUT, WIPE_FADE_BLACK, ENCOUNT_OLD_WIPEOUT_SYNC, 1, HEAPID_FIELD );
		*p_seq	= SEQ_MAIN;
		break;

	case SEQ_MAIN:
		if( WIPE_SYS_EndCheck() ) {
			*p_seq	= SEQ_EXIT;
		}
		break;

	case SEQ_EXIT:
		FLDHBLANK_SYS_Start( p_wk->p_hblank );
		*p_seq	= 0;
		return TRUE;

	default :
		GF_ASSERT( 0 );
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	サブシーケンス：時計回りに塗りつぶされる処理
 *
 *	@param	void *p_data	貰ったデータ
 *	@param	*p_seq			シーケンス
 *
 *	@retval	TRUE	終了
 *	@retval	FALSE	継続
 */
//-----------------------------------------------------------------------------
static BOOL ENCOLD_SUBSEQ_ClockFill( void *p_data, u32 *p_seq )
{
	enum  {
		SEQ_INIT,
		SEQ_MAIN,
		SEQ_EXIT,
	};
	ENCOUNT_TEST_OLD	*p_wk	= p_data;

	switch( *p_seq ) {
	case SEQ_INIT:
		FLDHBLANK_SYS_Stop( p_wk->p_hblank );
		WIPE_SYS_Start( WIPE_PATTERN_M, WIPE_TYPE_BOXOUT_INSIDE, WIPE_TYPE_BOXOUT_INSIDE, WIPE_FADE_BLACK, ENCOUNT_OLD_WIPEOUT_SYNC, 1, HEAPID_FIELD );
		*p_seq	= SEQ_MAIN;
		break;

	case SEQ_MAIN:
		if( WIPE_SYS_EndCheck() ) {
			*p_seq	= SEQ_EXIT;
		}
		break;

	case SEQ_EXIT:
		FLDHBLANK_SYS_Start( p_wk->p_hblank );
		*p_seq	= 0;
		return TRUE;

	default :
		GF_ASSERT( 0 );
	}

	return FALSE;
}


//----------------------------------------------------------------------------
/**
 *	@brief	簡易ボール読み込み
 *
 *	@param	p_clact	セルアクター
 *	@param	p_clsys	セルアクターシステム
 *	@param	p_clres	セルアクターリソースワーク
 *	@param	type	ボールの種類
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void ENC_CLACT_BALL_Load( ARCHANDLE* p_handle, CLACT_WORK_PTR *pp_clact, ENC_CLACT_SYS* p_clsys, ENC_CLACT_RES_WORK* p_clres, ENC_CLACT_BALL_TYPE type )
{
	static const struct {
		u32	NCGR;
		u32 NANR;
		u32 NCER;
		u32 NCLR;
	}ENC_BALL_RES_TBL[]	= {
		{ NARC_field_encounteffect_monsterball_old_NCGR, NARC_field_encounteffect_monsterball_old_NANR, NARC_field_encounteffect_monsterball_old_NCER, NARC_field_encounteffect_monsterball_old_NCLR },
		{ NARC_field_encounteffect_monstarballbig_oam_NCGR, NARC_field_encounteffect_monsterballbig_oam_NANR, NARC_field_encounteffect_monsterballbig_oam_NCER, NARC_field_encounteffect_monsterball_NCLR },
	};

	static const int ENCOUNT_BALL_MAT_X	= FX32_CONST(128);		// 開始座標
	static const int ENCOUNT_BALL_MAT_Y	= FX32_CONST(96);		// 開始座標

	GF_ASSERT( type != NELEMS(ENC_BALL_RES_TBL) );

	// グラフィック設定
	ENC_CLACT_ResLoadEasy(
			p_handle,
			p_clsys,
			p_clres,
			ENC_BALL_RES_TBL[type].NCLR, 1,
			ENC_BALL_RES_TBL[type].NCGR,
			ENC_BALL_RES_TBL[type].NCER,
			ENC_BALL_RES_TBL[type].NANR,
			600000
			);

	// アクター登録
	*pp_clact = ENC_CLACT_Add(
				p_clsys,
				p_clres,
				ENCOUNT_BALL_MAT_X,
				ENCOUNT_BALL_MAT_Y, 0, 0);
	CLACT_SetDrawFlag( *pp_clact, TRUE );
	CLACT_DrawPriorityChg( *pp_clact, 16 );
	CLACT_BGPriorityChg( *pp_clact, 1 );
}

static void EncountEffect_Field_GrassCore(TCB_PTR tcb, void * work, BOOL b_morning );

void EncountEffect_Field_GrassMorning(TCB_PTR tcb, void * work )
{
	EncountEffect_Field_GrassCore( tcb, work, TRUE );
}

void EncountEffect_Field_GrassNight(TCB_PTR tcb, void * work )
{
	EncountEffect_Field_GrassCore( tcb, work, FALSE );
}

//----------------------------------------------------------------------------
/**
 *	@brief	パタパタ閉じていくエフェクト
 *
 *	@param	tcb
 *	@param	work
 *
 *	@return
 */
//-----------------------------------------------------------------------------
static void EncountEffect_Field_GrassCore(TCB_PTR tcb, void * work, BOOL b_morning )
{
	//	シーケンス
	enum _SEQ {
		SEQ_INIT,
		SEQ_FLASH_INIT,
		SEQ_FLASH_MAIN,
		SEQ_PATAPATA_INIT,
		SEQ_PATAPATA_MAIN,
		SEQ_EXIT,
	};

	ENCOUNT_EFFECT_WORK		*eew	= work;
	ENCOUNT_TEST_PATAPATA	*tw		= eew->work;
	BOOL					result;

	switch( eew->seq ){
	//	初期化
	case SEQ_INIT:
		eew->work = sys_AllocMemory( HEAPID_FIELD, sizeof(ENCOUNT_TEST_PATAPATA) );
		memset( eew->work, 0, sizeof(ENCOUNT_TEST_PATAPATA) );
		tw	= eew->work;

		// ビットマップウィンドウ作成
		tw->p_bmp = GF_BGL_BmpWinAllocGet( HEAPID_FIELD, 1 );
		GF_BGL_BmpWinAdd( eew->fsw->bgl, tw->p_bmp, GF_BGL_FRAME3_M, 0, 0, 32, 32, 0, 0 );

		// カラーパレット転送
		{
			GXRgb color = 0;
			GF_BGL_PaletteSet( GF_BGL_FRAME3_M, &color, sizeof(GXRgb), 2*0xF );
		}

		GF_BGL_BmpWinDataFill( tw->p_bmp, 0 );
		GF_BGL_BmpWinOnVReq( tw->p_bmp );

		// オブジェクト作成
#ifdef ENCOUNT_PATAPATA_BGMSYNC
		tw->p_pata	= ENC_BMP_SYNCBGM_PataFillAlloc( HEAPID_FIELD );
#else
		tw->p_pata	= ENC_BMP_PatapataFillAlloc( HEAPID_FIELD );
#endif	//ENCOUNT_PATAPATA_BGMSYNC

		eew->seq	= SEQ_FLASH_INIT;
		break;

	//	フラッシュ初期化
	case SEQ_FLASH_INIT:
		{
			int val = ( b_morning ) ? 16 : -16;
			EncountFlashTask(MASK_MAIN_DISPLAY, val, val,  &eew->wait, 2);
		}
		eew->seq	= SEQ_FLASH_MAIN;
		break;

	//	フラッシュ処理
	case SEQ_FLASH_MAIN:
		if( eew->wait ){
			eew->seq	= SEQ_PATAPATA_INIT;
		}
		break;

	//	パタパタ初期化
	case SEQ_PATAPATA_INIT:
#ifdef	ENCOUNT_PATAPATA_BGMSYNC
		ENC_BMP_SYNCBGM_PataFillStart( tw->p_pata, 8, FX32_CONST(6)/48, tw->p_bmp, ENCOUNT_PATAPATA_BLOCK_FILLCOLOR );
#else
		ENC_BMP_PatapataFillStart( tw->p_pata, ENCOUNT_PATAPATA_START_SYNC, ENCOUNT_PATAPATA_FILL_SYNC, tw->p_bmp, ENCOUNT_PATAPATA_BLOCK_FILLCOLOR, b_morning );
#endif	//	ENCOUNT_PATAPATA_FILL_SYNC
		eew->seq	= SEQ_PATAPATA_MAIN;
		break;

	//	パタパタ処理
	case SEQ_PATAPATA_MAIN:
#ifdef ENCOUNT_PATAPATA_BGMSYNC
		result	= ENC_BMP_SYNCBGM_PataFillMain( tw->p_pata );
#else
		result	= ENC_BMP_PatapataFillMain( tw->p_pata );
#endif	//	ENCOUNT_PATAPATA_BGMSYNC
		GF_BGL_BmpWinOnVReq( tw->p_bmp );
		if( result ){
			eew->seq	= SEQ_EXIT;
		}
		break;

	//	終了処理
	case SEQ_EXIT:
		WIPE_SetBrightnessFadeOut( WIPE_FADE_BLACK );

		if(eew->end != NULL){
			*(eew->end) = TRUE;		// タスク終了を報告
		}

		//	ブラシ破棄
#ifdef ENCOUNT_PATAPATA_BGMSYNC
		ENC_BMP_SYNCBGM_PataFillDelete( tw->p_pata );
#else
		ENC_BMP_PatapataFillDelete( tw->p_pata );
#endif	//	ENCOUNT_PATAPATA_BGMSYNC
		// ビットマップ破棄
		GF_BGL_BmpWinOff( tw->p_bmp );
		GF_BGL_BmpWinDel( tw->p_bmp );
		GF_BGL_BmpWinFree( tw->p_bmp, 1 );

		ENC_End( eew, tcb );
		return ;
	}

}

void EncountEffect_Test_Patapata1(TCB_PTR tcb, void * work )
{
	//	シーケンス
	enum _SEQ {
		SEQ_INIT,
		SEQ_FLASH_INIT,
		SEQ_FLASH_MAIN,
		SEQ_PATAPATA_INIT,
		SEQ_PATAPATA_MAIN,
		SEQ_EXIT,
	};

	ENCOUNT_EFFECT_WORK		*eew	= work;
	ENCOUNT_TEST_PATAPATA	*tw		= eew->work;
	BOOL					result;

	switch( eew->seq ){
	//	初期化
	case SEQ_INIT:
		eew->work = sys_AllocMemory( HEAPID_FIELD, sizeof(ENCOUNT_TEST_PATAPATA) );
		memset( eew->work, 0, sizeof(ENCOUNT_TEST_PATAPATA) );
		tw	= eew->work;

		// ビットマップウィンドウ作成
		tw->p_bmp = GF_BGL_BmpWinAllocGet( HEAPID_FIELD, 1 );
		GF_BGL_BmpWinAdd( eew->fsw->bgl, tw->p_bmp, GF_BGL_FRAME3_M, 0, 0, 32, 32, 0, 0 );

		// カラーパレット転送
		{
			GXRgb color = 0;
			GF_BGL_PaletteSet( GF_BGL_FRAME3_M, &color, sizeof(GXRgb), 2*0xF );
		}

		GF_BGL_BmpWinDataFill( tw->p_bmp, 0 );
		GF_BGL_BmpWinOnVReq( tw->p_bmp );

		// オブジェクト作成
#ifdef ENCOUNT_PATAPATA_BGMSYNC
		tw->p_pata	= ENC_BMP_SYNCBGM_PataFillAlloc( HEAPID_FIELD );
#else
		tw->p_pata	= ENC_BMP_PatapataFillAlloc( HEAPID_FIELD );
#endif	//ENCOUNT_PATAPATA_BGMSYNC

		eew->seq	= SEQ_FLASH_INIT;
		break;

	//	フラッシュ初期化
	case SEQ_FLASH_INIT:
		EncountFlashTask(MASK_MAIN_DISPLAY, -16, -16,  &eew->wait, 2);
		eew->seq	= SEQ_FLASH_MAIN;
		break;

	//	フラッシュ処理
	case SEQ_FLASH_MAIN:
		if( eew->wait ){
			eew->seq	= SEQ_PATAPATA_INIT;
		}
		break;

	//	パタパタ初期化
	case SEQ_PATAPATA_INIT:
#ifdef	ENCOUNT_PATAPATA_BGMSYNC
		ENC_BMP_SYNCBGM_PataFillStart( tw->p_pata, 8, FX32_CONST(6)/48, tw->p_bmp, ENCOUNT_PATAPATA_BLOCK_FILLCOLOR );
#else
		ENC_BMP_PatapataFillStart( tw->p_pata, ENCOUNT_PATAPATA_START_SYNC, ENCOUNT_PATAPATA_FILL_SYNC, tw->p_bmp, ENCOUNT_PATAPATA_BLOCK_FILLCOLOR, TRUE );
#endif	//	ENCOUNT_PATAPATA_FILL_SYNC
		eew->seq	= SEQ_PATAPATA_MAIN;
		break;

	//	パタパタ処理
	case SEQ_PATAPATA_MAIN:
#ifdef ENCOUNT_PATAPATA_BGMSYNC
		result	= ENC_BMP_SYNCBGM_PataFillMain1( tw->p_pata );
#else
		result	= ENC_BMP_PatapataFillMain1( tw->p_pata );
#endif	//	ENCOUNT_PATAPATA_BGMSYNC
		GF_BGL_BmpWinOnVReq( tw->p_bmp );
		if( result ){
			eew->seq	= SEQ_EXIT;
		}
		break;

	//	終了処理
	case SEQ_EXIT:
		WIPE_SetBrightnessFadeOut( WIPE_FADE_BLACK );

		if(eew->end != NULL){
			*(eew->end) = TRUE;		// タスク終了を報告
		}

		//	ブラシ破棄
#ifdef ENCOUNT_PATAPATA_BGMSYNC
		ENC_BMP_SYNCBGM_PataFillDelete( tw->p_pata );
#else
		ENC_BMP_PatapataFillDelete( tw->p_pata );
#endif	//	ENCOUNT_PATAPATA_BGMSYNC
		// ビットマップ破棄
		GF_BGL_BmpWinOff( tw->p_bmp );
		GF_BGL_BmpWinDel( tw->p_bmp );
		GF_BGL_BmpWinFree( tw->p_bmp, 1 );

		ENC_End( eew, tcb );
		return ;
	}

}

void EncountEffect_Test_Patapata2(TCB_PTR tcb, void * work )
{
	//	シーケンス
	enum _SEQ {
		SEQ_INIT,
		SEQ_FLASH_INIT,
		SEQ_FLASH_MAIN,
		SEQ_PATAPATA_INIT,
		SEQ_PATAPATA_MAIN,
		SEQ_EXIT,
	};

	ENCOUNT_EFFECT_WORK		*eew	= work;
	ENCOUNT_TEST_PATAPATA	*tw		= eew->work;
	BOOL					result;

	switch( eew->seq ){
	//	初期化
	case SEQ_INIT:
		eew->work = sys_AllocMemory( HEAPID_FIELD, sizeof(ENCOUNT_TEST_PATAPATA) );
		memset( eew->work, 0, sizeof(ENCOUNT_TEST_PATAPATA) );
		tw	= eew->work;

		// ビットマップウィンドウ作成
		tw->p_bmp = GF_BGL_BmpWinAllocGet( HEAPID_FIELD, 1 );
		GF_BGL_BmpWinAdd( eew->fsw->bgl, tw->p_bmp, GF_BGL_FRAME3_M, 0, 0, 32, 32, 0, 0 );

		// カラーパレット転送
		{
			GXRgb color = 0;
			GF_BGL_PaletteSet( GF_BGL_FRAME3_M, &color, sizeof(GXRgb), 2*0xF );
		}

		GF_BGL_BmpWinDataFill( tw->p_bmp, 0 );
		GF_BGL_BmpWinOnVReq( tw->p_bmp );

		// オブジェクト作成
#ifdef ENCOUNT_PATAPATA_BGMSYNC
		tw->p_pata	= ENC_BMP_SYNCBGM_PataFillAlloc( HEAPID_FIELD );
#else
		tw->p_pata	= ENC_BMP_PatapataFillAlloc( HEAPID_FIELD );
#endif	//ENCOUNT_PATAPATA_BGMSYNC

		eew->seq	= SEQ_FLASH_INIT;
		break;

	//	フラッシュ初期化
	case SEQ_FLASH_INIT:
		EncountFlashTask(MASK_MAIN_DISPLAY, -16, -16,  &eew->wait, 2);
		eew->seq	= SEQ_FLASH_MAIN;
		break;

	//	フラッシュ処理
	case SEQ_FLASH_MAIN:
		if( eew->wait ){
			eew->seq	= SEQ_PATAPATA_INIT;
		}
		break;

	//	パタパタ初期化
	case SEQ_PATAPATA_INIT:
#ifdef	ENCOUNT_PATAPATA_BGMSYNC
		ENC_BMP_SYNCBGM_PataFillStart( tw->p_pata,8, FX32_CONST(6)/48, tw->p_bmp, ENCOUNT_PATAPATA_BLOCK_FILLCOLOR );
#else
		ENC_BMP_PatapataFillStart( tw->p_pata, ENCOUNT_PATAPATA_START_SYNC, ENCOUNT_PATAPATA_FILL_SYNC, tw->p_bmp, ENCOUNT_PATAPATA_BLOCK_FILLCOLOR, TRUE );
#endif	//	ENCOUNT_PATAPATA_FILL_SYNC
		eew->seq	= SEQ_PATAPATA_MAIN;
		break;

	//	パタパタ処理
	case SEQ_PATAPATA_MAIN:
#ifdef ENCOUNT_PATAPATA_BGMSYNC
		result	= ENC_BMP_SYNCBGM_PataFillMain2( tw->p_pata );
#else
		result	= ENC_BMP_PatapataFillMain2( tw->p_pata );
#endif	//	ENCOUNT_PATAPATA_BGMSYNC
		GF_BGL_BmpWinOnVReq( tw->p_bmp );
		if( result ){
			eew->seq	= SEQ_EXIT;
		}
		break;

	//	終了処理
	case SEQ_EXIT:
		WIPE_SetBrightnessFadeOut( WIPE_FADE_BLACK );

		if(eew->end != NULL){
			*(eew->end) = TRUE;		// タスク終了を報告
		}

		//	ブラシ破棄
#ifdef ENCOUNT_PATAPATA_BGMSYNC
		ENC_BMP_SYNCBGM_PataFillDelete( tw->p_pata );
#else
		ENC_BMP_PatapataFillDelete( tw->p_pata );
#endif	//	ENCOUNT_PATAPATA_BGMSYNC
		// ビットマップ破棄
		GF_BGL_BmpWinOff( tw->p_bmp );
		GF_BGL_BmpWinDel( tw->p_bmp );
		GF_BGL_BmpWinFree( tw->p_bmp, 1 );

		ENC_End( eew, tcb );
		return ;
	}

}

static void EncountEffect_Field_DanCore(TCB_PTR tcb, void * work, BOOL b_morning );

void EncountEffect_Field_DanMorning(TCB_PTR tcb, void * work )
{
	EncountEffect_Field_DanCore(tcb, work, TRUE );
}

void EncountEffect_Field_DanNight(TCB_PTR tcb, void * work )
{
	EncountEffect_Field_DanCore(tcb, work, FALSE );
}


static void EncountEffect_Field_DanCore(TCB_PTR tcb, void * work, BOOL b_morning )
{
	//	シーケンス
	enum _SEQ {
		SEQ_INIT,
		SEQ_FLASH_INIT,
		SEQ_FLASH_MAIN,
		SEQ_PATAPATA_INIT,
		SEQ_PATAPATA_MAIN,
		SEQ_EXIT,
	};

	ENCOUNT_EFFECT_WORK		*eew	= work;
	ENCOUNT_TEST_PATAPATA	*tw		= eew->work;
	BOOL					result;

	switch( eew->seq ){
	//	初期化
	case SEQ_INIT:
		eew->work = sys_AllocMemory( HEAPID_FIELD, sizeof(ENCOUNT_TEST_PATAPATA) );
		memset( eew->work, 0, sizeof(ENCOUNT_TEST_PATAPATA) );
		tw	= eew->work;

		// ビットマップウィンドウ作成
		tw->p_bmp = GF_BGL_BmpWinAllocGet( HEAPID_FIELD, 1 );
		GF_BGL_BmpWinAdd( eew->fsw->bgl, tw->p_bmp, GF_BGL_FRAME3_M, 0, 0, 32, 32, 0, 0 );

		// カラーパレット転送
		{
			GXRgb color = 0;
			GF_BGL_PaletteSet( GF_BGL_FRAME3_M, &color, sizeof(GXRgb), 2*0xF );
		}

		GF_BGL_BmpWinDataFill( tw->p_bmp, 0 );
		GF_BGL_BmpWinOnVReq( tw->p_bmp );

		// オブジェクト作成
#ifdef ENCOUNT_PATAPATA_BGMSYNC
		tw->p_pata	= ENC_BMP_SYNCBGM_PataFillAlloc( HEAPID_FIELD );
#else
		tw->p_pata	= ENC_BMP_PatapataFillAlloc( HEAPID_FIELD );
#endif	//ENCOUNT_PATAPATA_BGMSYNC

		eew->seq	= SEQ_FLASH_INIT;
		break;

	//	フラッシュ初期化
	case SEQ_FLASH_INIT:
		{
			int val = ( b_morning ) ? 16 : -16;
			EncountFlashTask(MASK_MAIN_DISPLAY, val, val,  &eew->wait, 2);
		}
		eew->seq	= SEQ_FLASH_MAIN;
		break;

	//	フラッシュ処理
	case SEQ_FLASH_MAIN:
		if( eew->wait ){
			eew->seq	= SEQ_PATAPATA_INIT;
		}
		break;

	//	パタパタ初期化
	case SEQ_PATAPATA_INIT:
#ifdef	ENCOUNT_PATAPATA_BGMSYNC
		ENC_BMP_SYNCBGM_PataFillStart( tw->p_pata, 8, FX32_CONST(6)/48, tw->p_bmp, ENCOUNT_PATAPATA_BLOCK_FILLCOLOR );
#else
		ENC_BMP_PatapataFillStart( tw->p_pata, ENCOUNT_PATAPATA_START_SYNC, ENCOUNT_PATAPATA_FILL_SYNC, tw->p_bmp, ENCOUNT_PATAPATA_BLOCK_FILLCOLOR, b_morning );
#endif	//	ENCOUNT_PATAPATA_FILL_SYNC
		eew->seq	= SEQ_PATAPATA_MAIN;
		break;

	//	パタパタ処理
	case SEQ_PATAPATA_MAIN:
#ifdef ENCOUNT_PATAPATA_BGMSYNC
		result	= ENC_BMP_SYNCBGM_PataFillMain3( tw->p_pata );
#else
		result	= ENC_BMP_PatapataFillMain3( tw->p_pata );
#endif	//	ENCOUNT_PATAPATA_BGMSYNC
		GF_BGL_BmpWinOnVReq( tw->p_bmp );
		if( result ){
			eew->seq	= SEQ_EXIT;
		}
		break;

	//	終了処理
	case SEQ_EXIT:
		WIPE_SetBrightnessFadeOut( WIPE_FADE_BLACK );

		if(eew->end != NULL){
			*(eew->end) = TRUE;		// タスク終了を報告
		}

		//	ブラシ破棄
#ifdef ENCOUNT_PATAPATA_BGMSYNC
		ENC_BMP_SYNCBGM_PataFillDelete( tw->p_pata );
#else
		ENC_BMP_PatapataFillDelete( tw->p_pata );
#endif	//	ENCOUNT_PATAPATA_BGMSYNC
		// ビットマップ破棄
		GF_BGL_BmpWinOff( tw->p_bmp );
		GF_BGL_BmpWinDel( tw->p_bmp );
		GF_BGL_BmpWinFree( tw->p_bmp, 1 );

		ENC_End( eew, tcb );
		return ;
	}

}

static void EncountEffect_Field_WaterCore(TCB_PTR tcb, void* work, BOOL b_morning);

void EncountEffect_Field_WaterMorning(TCB_PTR tcb, void* work)
{
	EncountEffect_Field_WaterCore(tcb, work, TRUE);
}

void EncountEffect_Field_WaterNight(TCB_PTR tcb, void* work)
{
	EncountEffect_Field_WaterCore(tcb, work, FALSE);
}


//-----------------------------------------------------------------------------
/**
 *	@brief	アーカイブからBGキャラを展開してUnpack（開放は行なわない）
 *
 *	@param	ARCHANDLE* p_handle
 *	@param	cgx_idx
 *	@param	outCharData
 *	@param	heap_id
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void* BG_LoadUnpackhara( ARCHANDLE* p_handle, int cgx_idx, NNSG2dCharacterData** outCharData, HEAPID heap_id )
{
	void* buff;
	NNSG2dCharacterData* charData;

	buff = ArcUtil_HDL_Load( p_handle, cgx_idx, FALSE, heap_id, ALLOC_TOP );
	NNS_G2dGetUnpackedBGCharacterData( buff, outCharData );

	return buff;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	スクリーン読み込み & 転送リクエスト
 *
 *	@param	GF_BGL_INI* p_bgl
 *	@param	p_handle
 *	@param	scrn_idx
 *	@param	frame
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void BG_LoadTransScreenVreq( GF_BGL_INI* p_bgl, ARCHANDLE* p_handle, int scrn_idx, int frame )
{
	void* buff;
	NNSG2dScreenData* p_scrn;

	// スクリーンデータ読み込み
	buff = ArcUtil_HDL_ScrnDataGet( p_handle, scrn_idx, FALSE, &p_scrn, HEAPID_FIELD );

	// スクリーンデータ書き込み
	GF_BGL_ScrWrite( p_bgl, frame,
			p_scrn->rawData, 0, 0,
			p_scrn->screenWidth / 8, p_scrn->screenHeight / 8 );

	// パレットをあわせる
	GF_BGL_ScrPalChange( p_bgl, frame, 0, 0, p_scrn->screenWidth / 8, p_scrn->screenHeight / 8,	0 );

	sys_FreeMemoryEz( buff );

	// スクリーンデータ転送
	GF_BGL_LoadScreenV_Req( p_bgl, frame );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	VIntrTCB BG転送
 *
 *	@param	TCB_PTR  tcb
 *	@param	work
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void VTCB_WaterBGCharaLoad( TCB_PTR  tcb, void* work )
{
	WATER_LOAD_WORK* wk = work;
	ENCOUNT_EFFECT_WORK* eew = wk->eew;

	switch( wk->vseq )
	{
		case 0 :
			GF_BGL_LoadCharacter( eew->fsw->bgl, GF_BGL_FRAME1_M,
				wk->charData1->pRawData, wk->charData1->szByte, 0 );
			wk->vseq++;
			break;
		case 1 :
			GF_BGL_LoadCharacter( eew->fsw->bgl, GF_BGL_FRAME3_M,
					wk->charData2->pRawData, wk->charData2->szByte, 0 );
			wk->vseq++;
			break;
		case 2 :
			wk->tcbVIntr = NULL;
			TCB_Delete( tcb );
			break;
		default : GF_ASSERT(0);
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	TCB BG転送
 *
 *	@param	TCB_PTR tcb
 *	@param	work
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void TCB_WaterLoadTask( TCB_PTR tcb, void* work )
{
	enum { WATER_LOAD_PAL_SIZE = 0x20 };
	WATER_LOAD_WORK* wk = work;
	ENCOUNT_EFFECT_WORK* eew = wk->eew;

	GF_ASSERT( eew->p_handle );
	switch( wk->seq )
	{
		case 0 :
			// -- パレット読み込み
			ArcUtil_HDL_PalSet( eew->p_handle, NARC_field_encounteffect_babble_NCLR,
					PALTYPE_MAIN_BG, 0, WATER_LOAD_PAL_SIZE, HEAPID_FIELD );

			// 全く同じパレットなので読み込む必要が意味がない
//			ArcUtil_HDL_PalSet( eew->p_handle, NARC_field_encounteffect_babble2_NCLR,
//					PALTYPE_MAIN_BG, 0, 0, HEAPID_FIELD );

			// -- キャラ展開
			wk->charBuff1 =	BG_LoadUnpackhara( eew->p_handle, NARC_field_encounteffect_babble_NCGR,
												&wk->charData1, HEAPID_FIELD );

			wk->charBuff2 =	BG_LoadUnpackhara( eew->p_handle, NARC_field_encounteffect_babble2_NCGR,
												&wk->charData2, HEAPID_FIELD );

			// Vブランク中にキャラ転送
			wk->vseq = 0;
			wk->tcbVIntr = VIntrTCB_Add( VTCB_WaterBGCharaLoad, wk, 0 );

			wk->seq++;
			break;
		case 1 :
			// 終了待ち
			if( wk->tcbVIntr == NULL )
			{
				// スクリーン読み込み&転送リクエスト
				BG_LoadTransScreenVreq( eew->fsw->bgl, eew->p_handle,
						NARC_field_encounteffect_babble_NSCR, GF_BGL_FRAME1_M );
				// スクリーン読み込み&転送リクエスト
				BG_LoadTransScreenVreq( eew->fsw->bgl, eew->p_handle,
						NARC_field_encounteffect_babble2_NSCR, GF_BGL_FRAME3_M );
				wk->seq++;
			}
			break;
		case 2 :
			sys_FreeMemoryEz( wk->charBuff1 );
			sys_FreeMemoryEz( wk->charBuff2 );

			wk->tcb = NULL;
			TCB_Delete( tcb );
			break;
		default : GF_ASSERT(0);
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	BGデータロード VIntrTCB 開始
 *
 *	@param	WATER_LOAD_WORK* wk
 *	@param	eew
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void WaterLoadTask_Start( WATER_LOAD_WORK* wk, ENCOUNT_EFFECT_WORK* eew )
{
	wk->eew = eew;
	wk->seq = 0;
	wk->tcb = TCB_Add( TCB_WaterLoadTask, wk, 1 );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	BGデータロード 終了待ち
 *
 *	@param	WATER_LOAD_WORK* wk
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static BOOL WaterLoadTask_CheckEnd( WATER_LOAD_WORK* wk )
{
	GF_ASSERT( wk );
	return ( wk->tcb == NULL );
}

//----------------------------------------------------------------------------
/**
 *	@brief	水場エフェクト
 *
 *	@param	tcb
 *	@param	work
 *
 *	@return
 */
//-----------------------------------------------------------------------------
static void EncountEffect_Field_WaterCore(TCB_PTR tcb, void* work, BOOL b_morning)
{
	//	シーケンス
	enum _SEQ {
		SEQ_INIT,
		SEQ_FLASH_INIT,
		SEQ_FLASH_MAIN,
		SEQ_LASTER_INIT,
		SEQ_LASTER_MAIN,
		SEQ_BG_INIT,
		SEQ_BG_MAIN,
		SEQ_EXIT,
	};

	ENCOUNT_EFFECT_WORK		*eew	= work;
	ENCOUNT_TEST_WATER		*tw		= eew->work;
	BOOL					result;
	int						i;

	switch( eew->seq ){
	//	初期化
	case SEQ_INIT:
		eew->work = sys_AllocMemory( HEAPID_FIELD, sizeof(ENCOUNT_TEST_WATER) );
		memset( eew->work, 0, sizeof(ENCOUNT_TEST_WATER) );
		tw	= eew->work;

		//
		// BG非表示のまま GF_BGL_BGControlSet を行なう(display.cでexternされている内部変数をダマす)
		//
		// ▼前提
		//
		//		・GF_Disp_GX_VisibleControl は内部変数で現在のディスプ状況を保持しており、
		//		　変更が行なわれない場合は return を返すように出来ている。
		//
		//		・GS環境下では GF_BGL_BGControlSet 内部で GF_Disp_GX_VisibleControl により 強制的にDISPがONになってしまう。
		//
		// ▼問題点
		//		エンカウントエフェクトでは暗転が入らない状態でBGControlをセットする必要があるので、DISPがONされると画面がパシってしまうことがある。
		//		(BTS2747,BTS2804などの原因)
		//
		// ▼処理内容
		//
		//		1. GF_Disp_GX_VisibleControl で GF_BGL_BGControlSet を行ないたい対象BGのディスプをONにする。
		//
		//		2. GX_SetVisiblePlane で直接ディスプレジスタを操作する。これにより、GF_Disp_GX_VisibleControl では 1でセットしたBGを操作できなくなる。
		//
		//		3. GF_BGL_BGControlSet を行なう。このとき、内部のGF_Disp_GX_VisibleControl でDISPがONになるのを防ぐことが出来る。
		//
		//		3. GF_Disp_GX_VisibleControlDirect で内部変数、レジスタを上書きしなおしてロックを解除する。
		//
		// これでパシり問題解決！ by hosaka genya
		//

		GF_Disp_GX_VisibleControl( GX_PLANEMASK_BG1, VISIBLE_ON );
		GF_Disp_GX_VisibleControl( GX_PLANEMASK_BG3, VISIBLE_ON );
		GX_SetVisiblePlane( GX_PLANEMASK_BG0 | GX_PLANEMASK_BG2 | GX_PLANEMASK_OBJ );

		//	BG設定
		{
			// MAIN DISP（エフェクト１）
			static const GF_BGL_BGCNT_HEADER TextBgCntDat1 = {
				0, 0, 0x1000, 0, GF_BGL_SCRSIZ_256x512, GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x1000, GX_BG_CHARBASE_0x04000, GX_BG_EXTPLTT_01,
				0, 0, 0, FALSE
			};
			GF_BGL_BGControlExit( eew->fsw->bgl, GF_BGL_FRAME1_M );
			GF_BGL_BGControlSet( eew->fsw->bgl, GF_BGL_FRAME1_M, &TextBgCntDat1, GF_BGL_MODE_TEXT );
			GF_BGL_ScrClear( eew->fsw->bgl, GF_BGL_FRAME1_M );

		}
		{
			// font用
			static const GF_BGL_BGCNT_HEADER TextBgCntDat2 = {
				0, 0, 0x1000, 0, GF_BGL_SCRSIZ_256x512, GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x2000, GX_BG_CHARBASE_0x08000, GX_BG_EXTPLTT_23,
				0, 0, 0, FALSE
			};
			GF_BGL_BGControlExit( eew->fsw->bgl, GF_BGL_FRAME3_M );
			GF_BGL_BGControlSet( eew->fsw->bgl, GF_BGL_FRAME3_M, &TextBgCntDat2, GF_BGL_MODE_TEXT );
			GF_BGL_ScrClear( eew->fsw->bgl, GF_BGL_FRAME3_M );
		}

		GF_BGL_PrioritySet( GX_PLANEMASK_BG1, 0 );
		GF_BGL_PrioritySet( GX_PLANEMASK_BG3, 0 );

		// ダマし解除
		GF_Disp_GX_VisibleControlDirect( GX_PLANEMASK_BG0 | GX_PLANEMASK_BG2 | GX_PLANEMASK_OBJ );

		WaterLoadTask_Start( &tw->wkLoad, eew );
		eew->seq	= SEQ_FLASH_INIT;
		break;
	//	フラッシュ初期化
	case SEQ_FLASH_INIT:

		// TCBが終了していなければ処理に入らない
		if( WaterLoadTask_CheckEnd( &tw->wkLoad ) == FALSE )
		{
			break;
		}

		// 背景色を黒に
		GF_BGL_BackGroundColorSet( GF_BGL_FRAME1_M, 0 );

		//	BG動作設定
		ENC_AddMoveReqFx( &tw->move_y1, ENCOUNT_TESTWATER_BG_START_Y, ENCOUNT_TESTWATER_BG_END_Y, ENCOUNT_TESTWATER_BG_START_ADD1, ENCOUNT_TESTWATER_BG1_SYNC );
		ENC_AddMoveReqFx( &tw->move_y2, ENCOUNT_TESTWATER_BG_START_Y, ENCOUNT_TESTWATER_BG_END_Y, ENCOUNT_TESTWATER_BG_START_ADD2, ENCOUNT_TESTWATER_BG2_SYNC );

		ENC_SinShakeMoveReq( &tw->shake_x, 0, 16, 15 );

		GF_BGL_ScrollReq( eew->fsw->bgl, GF_BGL_FRAME3_M, GF_BGL_SCROLL_Y_SET, tw->move_y1.x>>FX32_SHIFT );
		GF_BGL_ScrollReq( eew->fsw->bgl, GF_BGL_FRAME3_M, GF_BGL_SCROLL_X_SET, ENCOUNT_TESTWATER_BG_X );
		GF_BGL_ScrollReq( eew->fsw->bgl, GF_BGL_FRAME1_M, GF_BGL_SCROLL_Y_SET, tw->move_y2.x>>FX32_SHIFT );
		GF_BGL_ScrollReq( eew->fsw->bgl, GF_BGL_FRAME1_M, GF_BGL_SCROLL_X_SET, ENCOUNT_TESTWATER_BG_X );

		// タスク登録
		{
			int val = ( b_morning ) ? 16 : -16;
			EncountFlashTask(MASK_MAIN_DISPLAY, val, val,  &eew->wait, 2);
		}

		eew->seq	= SEQ_FLASH_MAIN;
		break;

	//	フラッシュ処理
	case SEQ_FLASH_MAIN:
		if( eew->wait ){
			// ラスター初期化
			ENC_Laster_Init( &tw->laster, HEAPID_FIELD );

			eew->seq	= SEQ_LASTER_INIT;
		}
		break;

	//	画面が波打つ初期化
	case SEQ_LASTER_INIT:
		tw->wait = ENCOUNT_TESTWATER_LASTER_SYNC;
		ENC_Laster_Start( &tw->laster,
				0, 191, ENCOUNT_TESTWATER_LASTER_SIN_ADDR,
				ENCOUNT_TESTWATER_LASTER_SIN_R, ENCOUNT_TESTWATER_LASTER_SPD,
				LASTER_SCROLL_MBG0, 0, ENCOUNT_TESTWATER_LASTER_TASK_PRI );

		tw->bg2_start	= 1;
		GF_Disp_GX_VisibleControl( GX_PLANEMASK_BG3, VISIBLE_ON );
		eew->seq	= SEQ_LASTER_MAIN;
		/* FALLTHROW */

	//	画面が波打つ処理
	case SEQ_LASTER_MAIN:
		if( tw->wait-- == 0 ){
			eew->seq	= SEQ_BG_INIT;
		}
		break;

	//	泡BG初期化
	case SEQ_BG_INIT:


		tw->bg1_start	= 1;
		GF_Disp_GX_VisibleControl( GX_PLANEMASK_BG1, VISIBLE_ON );
		eew->seq	= SEQ_BG_MAIN;
		break;

	//	泡BGが競りあがってくる処理
	case SEQ_BG_MAIN:
		if( tw->bg1_end ){
			eew->seq	= SEQ_EXIT;
		}
		break;


	//	終了処理
	case SEQ_EXIT:
		WIPE_SetBrightnessFadeOut( WIPE_FADE_BLACK );

		if(eew->end != NULL){
			*(eew->end) = TRUE;		// タスク終了を報告
		}

		ENC_Laster_Delete( &tw->laster );

		ENC_End( eew, tcb );
		return ;
	}


	if( tw->bg1_start ) {
		tw->bg1_end	= ENC_AddMoveMainFx( &tw->move_y1 );
		GF_BGL_ScrollReq( eew->fsw->bgl, GF_BGL_FRAME1_M, GF_BGL_SCROLL_Y_SET, tw->move_y1.x>>FX32_SHIFT );
	}
	if( tw->bg2_start ) {
		tw->bg2_end	= ENC_AddMoveMainFx( &tw->move_y2 );
		ENC_SinShakeMoveMain( &tw->shake_x );
		GF_BGL_ScrollReq( eew->fsw->bgl, GF_BGL_FRAME3_M, GF_BGL_SCROLL_Y_SET, tw->move_y2.x>>FX32_SHIFT );
		GF_BGL_ScrollReq( eew->fsw->bgl, GF_BGL_FRAME3_M, GF_BGL_SCROLL_X_SET, tw->shake_x.x );
	}
}

//-------------------------------------
///		ブラシで塗るようなエンカウント
//=====================================
typedef struct{
	GF_BGL_BMPWIN			*p_bmp;			// BMP本体
	ENC_BMP_CHR_BRUSH		*p_brush;		// ブラシワーク
} ENCOUNT_TEST_BRUSH;
//	ブラシで塗りつぶすようなエンカウントエフェクト
#define ENCOUNT_BRUSH_PIECE_SYNC		(3)		//	一直線塗るときのシンク
#define ENCOUNT_BRUSH_LINE_WIDTH		(48)	//	ライン間の幅

#define ENCOUNT_BRUSH_BLOCK_FILLCOLOR ( 15 )	// 塗りつぶし

//----------------------------------------------------------------------------
/**
 *	@brief	ブラシで塗りつぶされていくようなエフェクト
 *
 *	@param	tcb
 *	@param	work
 *
 *	@return
 */
//-----------------------------------------------------------------------------
void EncountEffect_Test_Brush(TCB_PTR tcb, void* work)
{
	//	シーケンス
	enum _SEQ {
		SEQ_INIT,
		SEQ_FLASH_INIT,
		SEQ_FLASH_MAIN,
		SEQ_BRUSH_INIT,
		SEQ_BRUSH_MAIN,
		SEQ_EXIT,
	};

	ENCOUNT_EFFECT_WORK		*eew	= work;
	ENCOUNT_TEST_BRUSH		*tw		= eew->work;
	BOOL					result;

	switch( eew->seq ){
	//	初期化
	case SEQ_INIT:
		eew->work = sys_AllocMemory( HEAPID_FIELD, sizeof(ENCOUNT_TEST_BRUSH) );
		memset( eew->work, 0, sizeof(ENCOUNT_TEST_BRUSH) );
		tw	= eew->work;

		// ビットマップウィンドウ作成
		tw->p_bmp = GF_BGL_BmpWinAllocGet( HEAPID_FIELD, 1 );
		GF_BGL_BmpWinAdd( eew->fsw->bgl, tw->p_bmp, GF_BGL_FRAME3_M, 0, 0, 32, 32, 0, 0 );

		// カラーパレット転送
		{
			GXRgb color = 0;
			GF_BGL_PaletteSet( GF_BGL_FRAME3_M, &color, sizeof(GXRgb), 2*0xF );
		}

		GF_BGL_BmpWinDataFill( tw->p_bmp, 0 );
		GF_BGL_BmpWinOnVReq( tw->p_bmp );

		// オブジェクト作成
		tw->p_brush	= ENC_BMP_ChrBrushAlloc( HEAPID_FIELD,NARC_field_encounteffect_brush_chr_NCGR );

		eew->seq	= SEQ_FLASH_INIT;
		break;

	//	フラッシュ初期化
	case SEQ_FLASH_INIT:
		EncountFlashTask(MASK_MAIN_DISPLAY, -16, -16,  &eew->wait, 2);
		eew->seq	= SEQ_FLASH_MAIN;
		break;

	//	フラッシュ処理
	case SEQ_FLASH_MAIN:
		if( eew->wait ){
			eew->seq	= SEQ_BRUSH_INIT;
		}
		break;

	//	ブラシ初期化
	case SEQ_BRUSH_INIT:
		ENC_BMP_ChrBrushStart( tw->p_brush, ENCOUNT_BRUSH_PIECE_SYNC, ENCOUNT_BRUSH_LINE_WIDTH, tw->p_bmp, ENCOUNT_BRUSH_BLOCK_FILLCOLOR );
		eew->seq	= SEQ_BRUSH_MAIN;
		break;

		//	ブラシ処理
	case SEQ_BRUSH_MAIN:
		result	= ENC_BMP_ChrBrushMain( tw->p_brush );
		GF_BGL_BmpWinOnVReq( tw->p_bmp );
		if( result ){
			eew->seq	= SEQ_EXIT;
		}
		break;

	//	終了処理
	case SEQ_EXIT:
		WIPE_SetBrightnessFadeOut( WIPE_FADE_BLACK );

		if(eew->end != NULL){
			*(eew->end) = TRUE;		// タスク終了を報告
		}

		//	ブラシ破棄
		ENC_BMP_ChrBrushDelete( tw->p_brush );

		// ビットマップ破棄
		GF_BGL_BmpWinOff( tw->p_bmp );
		GF_BGL_BmpWinDel( tw->p_bmp );
		GF_BGL_BmpWinFree( tw->p_bmp, 1 );

		ENC_End( eew, tcb );
		return ;
	}

}
